using System;

namespace HashLib.Crypto.SHA3
{
    internal class BlueMidnightWish224 : BlueMidnightWish256Base
    {
        public BlueMidnightWish224()
            : base(HashLib.HashSize.HashSize224)
        {
        }
    }

    internal class BlueMidnightWish256 : BlueMidnightWish256Base
    {
        public BlueMidnightWish256()
            : base(HashLib.HashSize.HashSize256)
        {
        }
    }

    internal class BlueMidnightWish384 : BlueMidnightWish512Base
    {
        public BlueMidnightWish384()
            : base(HashLib.HashSize.HashSize384)
        {
        }
    }

    internal class BlueMidnightWish512 : BlueMidnightWish512Base
    {
        public BlueMidnightWish512()
            : base(HashLib.HashSize.HashSize512)
        {
        }
    }

    internal abstract class BlueMidnightWishBase : BlockHash, ICryptoNotBuildIn
    {
        public BlueMidnightWishBase(int a_block_size, HashSize a_hash_size)
            : base((int)a_hash_size, a_block_size)
        {
        }

        public override void Initialize()
        {
            base.Initialize();
        }

        protected override void Finish()
        {
            ulong bits = m_processed_bytes * 8;

            int padindex = BlockSize - m_buffer.Pos - 8;

            if (m_buffer.Pos >= BlockSize - 8)
                padindex += BlockSize;

            byte[] pad = new byte[padindex + 8];

            pad[0] = 0x80;

            Converters.ConvertULongToBytes(bits, pad, padindex);
            padindex += 8;

            TransformBytes(pad, 0, padindex);

            FinalCompression();
        }

        protected abstract void FinalCompression();
    }

    internal abstract class BlueMidnightWish256Base : BlueMidnightWishBase
    {
        #region Consts
        private static readonly uint[] s_initial_state_224 = 
            {   
                0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 
                0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f, 
                0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f, 
                0x30313233, 0x34353637, 0x38393a3b, 0x3c3d3e3f, 
            };

        private static readonly uint[] s_initial_state_256 = 
            {   
                0x40414243, 0x44454647, 0x48494a4b, 0x4c4d4e4f, 
                0x50515253, 0x54555657, 0x58595a5b, 0x5c5d5e5f, 
                0x60616263, 0x64656667, 0x68696a6b, 0x6c6d6e6f, 
                0x70717273, 0x74757677, 0x78797a7b, 0x7c7d7e7f, 
            };
        #endregion

        private readonly uint[] m_state = new uint[32];

        public BlueMidnightWish256Base(HashSize a_hash_size)
            : base(64, a_hash_size)
        {
            Initialize();
        }

        protected override void TransformBlock(byte[] a_data, int a_index)
        {
            uint[] data = Converters.ConvertBytesToUInts(a_data, a_index, 64);

            uint p256_00 = m_state[0] ^ data[0];
            uint p256_01 = m_state[1] ^ data[1];
            uint p256_02 = m_state[2] ^ data[2];
            uint p256_03 = m_state[3] ^ data[3];
            uint p256_04 = m_state[4] ^ data[4];
            uint p256_05 = m_state[5] ^ data[5];
            uint p256_06 = m_state[6] ^ data[6];
            uint p256_07 = m_state[7] ^ data[7];
            uint p256_08 = m_state[8] ^ data[8];
            uint p256_09 = m_state[9] ^ data[9];
            uint p256_10 = m_state[10] ^ data[10];
            uint p256_11 = m_state[11] ^ data[11];
            uint p256_12 = m_state[12] ^ data[12];
            uint p256_13 = m_state[13] ^ data[13];
            uint p256_14 = m_state[14] ^ data[14];
            uint p256_15 = m_state[15] ^ data[15];

            uint td32_00 = (data[0] << 1) | (data[0] >> 31);
            uint td32_01 = (data[1] << 2) | (data[1] >> 30);
            uint td32_02 = (data[2] << 3) | (data[2] >> 29);
            uint td32_03 = (data[3] << 4) | (data[3] >> 28);
            uint td32_04 = (data[4] << 5) | (data[4] >> 27);
            uint td32_05 = (data[5] << 6) | (data[5] >> 26);
            uint td32_06 = (data[6] << 7) | (data[6] >> 25);
            uint td32_07 = (data[7] << 8) | (data[7] >> 24);
            uint td32_08 = (data[8] << 9) | (data[8] >> 23);
            uint td32_09 = (data[9] << 10) | (data[9] >> 22);
            uint td32_10 = (data[10] << 11) | (data[10] >> 21);
            uint td32_11 = (data[11] << 12) | (data[11] >> 20);
            uint td32_12 = (data[12] << 13) | (data[12] >> 19);
            uint td32_13 = (data[13] << 14) | (data[13] >> 18);
            uint td32_14 = (data[14] << 15) | (data[14] >> 17);
            uint td32_15 = (data[15] << 16) | (data[15] >> 16);

            uint t256_16 = p256_01 - p256_14;
            uint t256_17 = p256_15 - p256_12;
            uint t256_18 = p256_14 - p256_07;
            uint t256_19 = p256_13 - p256_06;
            uint t256_20 = p256_08 - p256_05;
            uint t256_21 = p256_08 - p256_01;

            uint p256_16 = (p256_05 + t256_18 + p256_10 + p256_13);
            p256_16 = ((p256_16 >> 1) ^ (p256_16 << 3) ^ ((p256_16 << 4) | (p256_16 >> 28)) ^ ((p256_16 << 19) | (p256_16 >> 13))) + m_state[1];
            uint p256_17 = (p256_06 - p256_08 + p256_11 + p256_14 - p256_15);
            p256_17 = ((p256_17 >> 1) ^ (p256_17 << 2) ^ ((p256_17 << 8) | (p256_17 >> 24)) ^ ((p256_17 << 23) | (p256_17 >> 9))) + m_state[2];
            uint p256_18 = (p256_00 + p256_07 + p256_09 + t256_17);
            p256_18 = ((p256_18 >> 2) ^ (p256_18 << 1) ^ ((p256_18 << 12) | (p256_18 >> 20)) ^ ((p256_18 << 25) | (p256_18 >> 7))) + m_state[3];
            uint p256_19 = (p256_00 + t256_21 - p256_10 + p256_13);
            p256_19 = ((p256_19 >> 2) ^ (p256_19 << 2) ^ ((p256_19 << 15) | (p256_19 >> 17)) ^ ((p256_19 << 29) | (p256_19 >> 3))) + m_state[4];
            uint p256_20 = (t256_16 + p256_02 + p256_09 - p256_11);
            p256_20 = ((p256_20 >> 1) ^ p256_20) + m_state[5];
            uint p256_21 = (p256_03 - p256_02 + p256_10 + t256_17);
            p256_21 = ((p256_21 >> 1) ^ (p256_21 << 3) ^ ((p256_21 << 4) | (p256_21 >> 28)) ^ ((p256_21 << 19) | (p256_21 >> 13))) + m_state[6];
            uint p256_22 = (p256_04 - p256_00 - p256_03 - p256_11 + p256_13);
            p256_22 = ((p256_22 >> 1) ^ (p256_22 << 2) ^ ((p256_22 << 8) | (p256_22 >> 24)) ^ ((p256_22 << 23) | (p256_22 >> 9))) + m_state[7];
            uint p256_23 = (t256_16 - p256_04 - p256_05 - p256_12);
            p256_23 = ((p256_23 >> 2) ^ (p256_23 << 1) ^ ((p256_23 << 12) | (p256_23 >> 20)) ^ ((p256_23 << 25) | (p256_23 >> 7))) + m_state[8];
            uint p256_24 = (p256_02 - p256_05 + t256_19 - p256_15);
            p256_24 = ((p256_24 >> 2) ^ (p256_24 << 2) ^ ((p256_24 << 15) | (p256_24 >> 17)) ^ ((p256_24 << 29) | (p256_24 >> 3))) + m_state[9];
            uint p256_25 = (p256_00 - p256_03 + p256_06 + t256_18);
            p256_25 = ((p256_25 >> 1) ^ p256_25) + m_state[10];
            uint p256_26 = (t256_21 - p256_04 - p256_07 + p256_15);
            p256_26 = ((p256_26 >> 1) ^ (p256_26 << 3) ^ ((p256_26 << 4) | (p256_26 >> 28)) ^ ((p256_26 << 19) | (p256_26 >> 13))) + m_state[11];
            uint p256_27 = (t256_20 - p256_00 - p256_02 + p256_09);
            p256_27 = ((p256_27 >> 1) ^ (p256_27 << 2) ^ ((p256_27 << 8) | (p256_27 >> 24)) ^ ((p256_27 << 23) | (p256_27 >> 9))) + m_state[12];
            uint p256_28 = (p256_01 + p256_03 - p256_06 - p256_09 + p256_10);
            p256_28 = ((p256_28 >> 2) ^ (p256_28 << 1) ^ ((p256_28 << 12) | (p256_28 >> 20)) ^ ((p256_28 << 25) | (p256_28 >> 7))) + m_state[13];
            uint p256_29 = (p256_02 + p256_04 + p256_07 + p256_10 + p256_11);
            p256_29 = ((p256_29 >> 2) ^ (p256_29 << 2) ^ ((p256_29 << 15) | (p256_29 >> 17)) ^ ((p256_29 << 29) | (p256_29 >> 3))) + m_state[14];
            uint p256_30 = (p256_03 + t256_20 - p256_11 - p256_12);
            p256_14 = ((p256_30 >> 1) ^ p256_30) + m_state[15];
            uint p256_31 = (p256_12 - p256_04 + t256_19 - p256_09);
            p256_15 = ((p256_31 >> 1) ^ (p256_31 << 3) ^ ((p256_31 << 4) | (p256_31 >> 28)) ^ ((p256_31 << 19) | (p256_31 >> 13))) + m_state[0];

            p256_00 = p256_16;
            p256_01 = p256_17;
            p256_02 = p256_18;
            p256_03 = p256_19;
            p256_04 = p256_20;
            p256_05 = p256_21;
            p256_06 = p256_22;
            p256_07 = p256_23;
            p256_08 = p256_24;
            p256_09 = p256_25;
            p256_10 = p256_26;
            p256_11 = p256_27;
            p256_12 = p256_28;
            p256_13 = p256_29;

            p256_16 = ((p256_00 >> 1) ^ (p256_00 << 2) ^ ((p256_00 << 8) | (p256_00 >> 24)) ^ ((p256_00 << 23) | (p256_00 >> 9))) +
                      ((p256_01 >> 2) ^ (p256_01 << 1) ^ ((p256_01 << 12) | (p256_01 >> 20)) ^ ((p256_01 << 25) | (p256_01 >> 7))) +
                      ((p256_02 >> 2) ^ (p256_02 << 2) ^ ((p256_02 << 15) | (p256_02 >> 17)) ^ ((p256_02 << 29) | (p256_02 >> 3))) +
                      ((p256_03 >> 1) ^ (p256_03 << 3) ^ ((p256_03 << 4) | (p256_03 >> 28)) ^ ((p256_03 << 19) | (p256_03 >> 13))) +
                      ((p256_04 >> 1) ^ (p256_04 << 2) ^ ((p256_04 << 8) | (p256_04 >> 24)) ^ ((p256_04 << 23) | (p256_04 >> 9))) +
                      ((p256_05 >> 2) ^ (p256_05 << 1) ^ ((p256_05 << 12) | (p256_05 >> 20)) ^ ((p256_05 << 25) | (p256_05 >> 7))) +
                      ((p256_06 >> 2) ^ (p256_06 << 2) ^ ((p256_06 << 15) | (p256_06 >> 17)) ^ ((p256_06 << 29) | (p256_06 >> 3))) +
                      ((p256_07 >> 1) ^ (p256_07 << 3) ^ ((p256_07 << 4) | (p256_07 >> 28)) ^ ((p256_07 << 19) | (p256_07 >> 13))) +
                      ((p256_08 >> 1) ^ (p256_08 << 2) ^ ((p256_08 << 8) | (p256_08 >> 24)) ^ ((p256_08 << 23) | (p256_08 >> 9))) +
                      ((p256_09 >> 2) ^ (p256_09 << 1) ^ ((p256_09 << 12) | (p256_09 >> 20)) ^ ((p256_09 << 25) | (p256_09 >> 7))) +
                      ((p256_10 >> 2) ^ (p256_10 << 2) ^ ((p256_10 << 15) | (p256_10 >> 17)) ^ ((p256_10 << 29) | (p256_10 >> 3))) +
                      ((p256_11 >> 1) ^ (p256_11 << 3) ^ ((p256_11 << 4) | (p256_11 >> 28)) ^ ((p256_11 << 19) | (p256_11 >> 13))) +
                      ((p256_12 >> 1) ^ (p256_12 << 2) ^ ((p256_12 << 8) | (p256_12 >> 24)) ^ ((p256_12 << 23) | (p256_12 >> 9))) +
                      ((p256_13 >> 2) ^ (p256_13 << 1) ^ ((p256_13 << 12) | (p256_13 >> 20)) ^ ((p256_13 << 25) | (p256_13 >> 7))) +
                      ((p256_14 >> 2) ^ (p256_14 << 2) ^ ((p256_14 << 15) | (p256_14 >> 17)) ^ ((p256_14 << 29) | (p256_14 >> 3))) +
                      ((p256_15 >> 1) ^ (p256_15 << 3) ^ ((p256_15 << 4) | (p256_15 >> 28)) ^ ((p256_15 << 19) | (p256_15 >> 13))) +
                      ((td32_00 + td32_03 - td32_10 + 0x55555550) ^ m_state[7]);

            uint XL32 = p256_16;

            p256_17 = ((p256_01 >> 1) ^ (p256_01 << 2) ^ ((p256_01 << 8) | (p256_01 >> 24)) ^ ((p256_01 << 23) | (p256_01 >> 9))) +
                      ((p256_02 >> 2) ^ (p256_02 << 1) ^ ((p256_02 << 12) | (p256_02 >> 20)) ^ ((p256_02 << 25) | (p256_02 >> 7))) +
                      ((p256_03 >> 2) ^ (p256_03 << 2) ^ ((p256_03 << 15) | (p256_03 >> 17)) ^ ((p256_03 << 29) | (p256_03 >> 3))) +
                      ((p256_04 >> 1) ^ (p256_04 << 3) ^ ((p256_04 << 4) | (p256_04 >> 28)) ^ ((p256_04 << 19) | (p256_04 >> 13))) +
                      ((p256_05 >> 1) ^ (p256_05 << 2) ^ ((p256_05 << 8) | (p256_05 >> 24)) ^ ((p256_05 << 23) | (p256_05 >> 9))) +
                      ((p256_06 >> 2) ^ (p256_06 << 1) ^ ((p256_06 << 12) | (p256_06 >> 20)) ^ ((p256_06 << 25) | (p256_06 >> 7))) +
                      ((p256_07 >> 2) ^ (p256_07 << 2) ^ ((p256_07 << 15) | (p256_07 >> 17)) ^ ((p256_07 << 29) | (p256_07 >> 3))) +
                      ((p256_08 >> 1) ^ (p256_08 << 3) ^ ((p256_08 << 4) | (p256_08 >> 28)) ^ ((p256_08 << 19) | (p256_08 >> 13))) +
                      ((p256_09 >> 1) ^ (p256_09 << 2) ^ ((p256_09 << 8) | (p256_09 >> 24)) ^ ((p256_09 << 23) | (p256_09 >> 9))) +
                      ((p256_10 >> 2) ^ (p256_10 << 1) ^ ((p256_10 << 12) | (p256_10 >> 20)) ^ ((p256_10 << 25) | (p256_10 >> 7))) +
                      ((p256_11 >> 2) ^ (p256_11 << 2) ^ ((p256_11 << 15) | (p256_11 >> 17)) ^ ((p256_11 << 29) | (p256_11 >> 3))) +
                      ((p256_12 >> 1) ^ (p256_12 << 3) ^ ((p256_12 << 4) | (p256_12 >> 28)) ^ ((p256_12 << 19) | (p256_12 >> 13))) +
                      ((p256_13 >> 1) ^ (p256_13 << 2) ^ ((p256_13 << 8) | (p256_13 >> 24)) ^ ((p256_13 << 23) | (p256_13 >> 9))) +
                      ((p256_14 >> 2) ^ (p256_14 << 1) ^ ((p256_14 << 12) | (p256_14 >> 20)) ^ ((p256_14 << 25) | (p256_14 >> 7))) +
                      ((p256_15 >> 2) ^ (p256_15 << 2) ^ ((p256_15 << 15) | (p256_15 >> 17)) ^ ((p256_15 << 29) | (p256_15 >> 3))) +
                      ((p256_16 >> 1) ^ (p256_16 << 3) ^ ((p256_16 << 4) | (p256_16 >> 28)) ^ ((p256_16 << 19) | (p256_16 >> 13))) +
                      ((td32_01 + td32_04 - td32_11 + 0x5aaaaaa5) ^ m_state[8]);

            XL32 ^= p256_17;
            uint TempEven32 = p256_14 + p256_12 + p256_10 + p256_08 + p256_06 + p256_04 + p256_02;
            uint TempOdd32 = p256_15 + p256_13 + p256_11 + p256_09 + p256_07 + p256_05 + p256_03;

            p256_18 = TempEven32 +
                      ((p256_03 << 3) | (p256_03 >> 29)) +
                      ((p256_05 << 7) | (p256_05 >> 25)) +
                      ((p256_07 << 13) | (p256_07 >> 19)) +
                      ((p256_09 << 16) | (p256_09 >> 16)) +
                      ((p256_11 << 19) | (p256_11 >> 13)) +
                      ((p256_13 << 23) | (p256_13 >> 9)) +
                      ((p256_15 << 27) | (p256_15 >> 5)) +
                      ((p256_16 >> 1) ^ p256_16) +
                      ((p256_17 >> 2) ^ p256_17) +
                      ((td32_02 + td32_05 - td32_12 + 0x5ffffffa) ^ m_state[9]);

            XL32 ^= p256_18;

            p256_19 = TempOdd32 +
                      ((p256_04 << 3) | (p256_04 >> 29)) +
                      ((p256_06 << 7) | (p256_06 >> 25)) +
                      ((p256_08 << 13) | (p256_08 >> 19)) +
                      ((p256_10 << 16) | (p256_10 >> 16)) +
                      ((p256_12 << 19) | (p256_12 >> 13)) +
                      ((p256_14 << 23) | (p256_14 >> 9)) +
                      ((p256_16 << 27) | (p256_16 >> 5)) +
                      ((p256_17 >> 1) ^ p256_17) +
                      ((p256_18 >> 2) ^ p256_18) +
                      ((td32_03 + td32_06 - td32_13 + 0x6555554f) ^ m_state[10]);

            XL32 ^= p256_19;
            TempEven32 = TempEven32 + p256_16 - p256_02;

            p256_20 = TempEven32 +
                      ((p256_05 << 3) | (p256_05 >> 29)) +
                      ((p256_07 << 7) | (p256_07 >> 25)) +
                      ((p256_09 << 13) | (p256_09 >> 19)) +
                      ((p256_11 << 16) | (p256_11 >> 16)) +
                      ((p256_13 << 19) | (p256_13 >> 13)) +
                      ((p256_15 << 23) | (p256_15 >> 9)) +
                      ((p256_17 << 27) | (p256_17 >> 5)) +
                      ((p256_18 >> 1) ^ p256_18) +
                      ((p256_19 >> 2) ^ p256_19) +
                      ((td32_04 + td32_07 - td32_14 + 0x6aaaaaa4) ^ m_state[11]);

            XL32 ^= p256_20;
            TempOdd32 = TempOdd32 + p256_17 - p256_03;

            p256_21 = TempOdd32 +
                      ((p256_06 << 3) | (p256_06 >> 29)) +
                      ((p256_08 << 7) | (p256_08 >> 25)) +
                      ((p256_10 << 13) | (p256_10 >> 19)) +
                      ((p256_12 << 16) | (p256_12 >> 16)) +
                      ((p256_14 << 19) | (p256_14 >> 13)) +
                      ((p256_16 << 23) | (p256_16 >> 9)) +
                      ((p256_18 << 27) | (p256_18 >> 5)) +
                      ((p256_19 >> 1) ^ p256_19) +
                      ((p256_20 >> 2) ^ p256_20) +
                      ((td32_05 + td32_08 - td32_15 + 0x6ffffff9) ^ m_state[12]);

            XL32 ^= p256_21;
            TempEven32 = TempEven32 + p256_18 - p256_04;

            p256_22 = TempEven32 +
                      ((p256_07 << 3) | (p256_07 >> 29)) +
                      ((p256_09 << 7) | (p256_09 >> 25)) +
                      ((p256_11 << 13) | (p256_11 >> 19)) +
                      ((p256_13 << 16) | (p256_13 >> 16)) +
                      ((p256_15 << 19) | (p256_15 >> 13)) +
                      ((p256_17 << 23) | (p256_17 >> 9)) +
                      ((p256_19 << 27) | (p256_19 >> 5)) +
                      ((p256_20 >> 1) ^ p256_20) +
                      ((p256_21 >> 2) ^ p256_21) +
                      ((td32_06 + td32_09 - td32_00 + 0x7555554e) ^ m_state[13]);

            XL32 ^= p256_22;
            TempOdd32 = TempOdd32 + p256_19 - p256_05;

            p256_23 = TempOdd32 +
                      ((p256_08 << 3) | (p256_08 >> 29)) +
                      ((p256_10 << 7) | (p256_10 >> 25)) +
                      ((p256_12 << 13) | (p256_12 >> 19)) +
                      ((p256_14 << 16) | (p256_14 >> 16)) +
                      ((p256_16 << 19) | (p256_16 >> 13)) +
                      ((p256_18 << 23) | (p256_18 >> 9)) +
                      ((p256_20 << 27) | (p256_20 >> 5)) +
                      ((p256_21 >> 1) ^ p256_21) +
                      ((p256_22 >> 2) ^ p256_22) +
                      ((td32_07 + td32_10 - td32_01 + 0x7aaaaaa3) ^ m_state[14]);

            XL32 ^= p256_23;
            TempEven32 = TempEven32 + p256_20 - p256_06;

            p256_24 = TempEven32 +
                      ((p256_09 << 3) | (p256_09 >> 29)) +
                      ((p256_11 << 7) | (p256_11 >> 25)) +
                      ((p256_13 << 13) | (p256_13 >> 19)) +
                      ((p256_15 << 16) | (p256_15 >> 16)) +
                      ((p256_17 << 19) | (p256_17 >> 13)) +
                      ((p256_19 << 23) | (p256_19 >> 9)) +
                      ((p256_21 << 27) | (p256_21 >> 5)) +
                      ((p256_22 >> 1) ^ p256_22) +
                      ((p256_23 >> 2) ^ p256_23) +
                      ((td32_08 + td32_11 - td32_02 + 0x7ffffff8) ^ m_state[15]);

            uint XH32 = XL32 ^ p256_24;
            TempOdd32 = TempOdd32 + p256_21 - p256_07;

            p256_25 = TempOdd32 +
                      ((p256_10 << 3) | (p256_10 >> 29)) +
                      ((p256_12 << 7) | (p256_12 >> 25)) +
                      ((p256_14 << 13) | (p256_14 >> 19)) +
                      ((p256_16 << 16) | (p256_16 >> 16)) +
                      ((p256_18 << 19) | (p256_18 >> 13)) +
                      ((p256_20 << 23) | (p256_20 >> 9)) +
                      ((p256_22 << 27) | (p256_22 >> 5)) +
                      ((p256_23 >> 1) ^ p256_23) +
                      ((p256_24 >> 2) ^ p256_24) +
                      ((td32_09 + td32_12 - td32_03 + 0x8555554d) ^ m_state[0]);

            XH32 ^= p256_25;
            TempEven32 = TempEven32 + p256_22 - p256_08;

            p256_26 = TempEven32 +
                      ((p256_11 << 3) | (p256_11 >> 29)) +
                      ((p256_13 << 7) | (p256_13 >> 25)) +
                      ((p256_15 << 13) | (p256_15 >> 19)) +
                      ((p256_17 << 16) | (p256_17 >> 16)) +
                      ((p256_19 << 19) | (p256_19 >> 13)) +
                      ((p256_21 << 23) | (p256_21 >> 9)) +
                      ((p256_23 << 27) | (p256_23 >> 5)) +
                      ((p256_24 >> 1) ^ p256_24) +
                      ((p256_25 >> 2) ^ p256_25) +
                      ((td32_10 + td32_13 - td32_04 + 0x8aaaaaa2) ^ m_state[1]);

            XH32 ^= p256_26;
            TempOdd32 = TempOdd32 + p256_23 - p256_09;

            p256_27 = TempOdd32 +
                      ((p256_12 << 3) | (p256_12 >> 29)) +
                      ((p256_14 << 7) | (p256_14 >> 25)) +
                      ((p256_16 << 13) | (p256_16 >> 19)) +
                      ((p256_18 << 16) | (p256_18 >> 16)) +
                      ((p256_20 << 19) | (p256_20 >> 13)) +
                      ((p256_22 << 23) | (p256_22 >> 9)) +
                      ((p256_24 << 27) | (p256_24 >> 5)) +
                      ((p256_25 >> 1) ^ p256_25) +
                      ((p256_26 >> 2) ^ p256_26) +
                      ((td32_11 + td32_14 - td32_05 + 0x8ffffff7) ^ m_state[2]);

            XH32 ^= p256_27;
            TempEven32 = TempEven32 + p256_24 - p256_10;

            p256_28 = TempEven32 +
                      ((p256_13 << 3) | (p256_13 >> 29)) +
                      ((p256_15 << 7) | (p256_15 >> 25)) +
                      ((p256_17 << 13) | (p256_17 >> 19)) +
                      ((p256_19 << 16) | (p256_19 >> 16)) +
                      ((p256_21 << 19) | (p256_21 >> 13)) +
                      ((p256_23 << 23) | (p256_23 >> 9)) +
                      ((p256_25 << 27) | (p256_25 >> 5)) +
                      ((p256_26 >> 1) ^ p256_26) + ((p256_27 >> 2) ^ p256_27) +
                      ((td32_12 + td32_15 - td32_06 + 0x9555554c) ^ m_state[3]);

            XH32 ^= p256_28;
            TempOdd32 = TempOdd32 + p256_25 - p256_11;

            p256_29 = TempOdd32 +
                      ((p256_14 << 3) | (p256_14 >> 29)) +
                      ((p256_16 << 7) | (p256_16 >> 25)) +
                      ((p256_18 << 13) | (p256_18 >> 19)) +
                      ((p256_20 << 16) | (p256_20 >> 16)) +
                      ((p256_22 << 19) | (p256_22 >> 13)) +
                      ((p256_24 << 23) | (p256_24 >> 9)) +
                      ((p256_26 << 27) | (p256_26 >> 5)) +
                      ((p256_27 >> 1) ^ p256_27) +
                      ((p256_28 >> 2) ^ p256_28) +
                      ((td32_13 + td32_00 - td32_07 + 0x9aaaaaa1) ^ m_state[4]);

            XH32 ^= p256_29;
            TempEven32 = TempEven32 + p256_26 - p256_12;

            p256_30 = TempEven32 +
                      ((p256_15 << 3) | (p256_15 >> 29)) +
                      ((p256_17 << 7) | (p256_17 >> 25)) +
                      ((p256_19 << 13) | (p256_19 >> 19)) +
                      ((p256_21 << 16) | (p256_21 >> 16)) +
                      ((p256_23 << 19) | (p256_23 >> 13)) +
                      ((p256_25 << 23) | (p256_25 >> 9)) +
                      ((p256_27 << 27) | (p256_27 >> 5)) +
                      ((p256_28 >> 1) ^ p256_28) +
                      ((p256_29 >> 2) ^ p256_29) +
                      ((td32_14 + td32_01 - td32_08 + 0x9ffffff6) ^ m_state[5]);

            XH32 ^= p256_30;
            TempOdd32 = TempOdd32 + p256_27 - p256_13;

            p256_31 = TempOdd32 +
                      ((p256_16 << 3) | (p256_16 >> 29)) +
                      ((p256_18 << 7) | (p256_18 >> 25)) +
                      ((p256_20 << 13) | (p256_20 >> 19)) +
                      ((p256_22 << 16) | (p256_22 >> 16)) +
                      ((p256_24 << 19) | (p256_24 >> 13)) +
                      ((p256_26 << 23) | (p256_26 >> 9)) +
                      ((p256_28 << 27) | (p256_28 >> 5)) +
                      ((p256_29 >> 1) ^ p256_29) +
                      ((p256_30 >> 2) ^ p256_30) +
                      ((td32_15 + td32_02 - td32_09 + 0xa555554b) ^ m_state[6]);

            XH32 ^= p256_31;

            m_state[0] = ((XH32 << 5) ^ (p256_16 >> 5) ^ data[0]) + (XL32 ^ p256_24 ^ p256_00);
            m_state[1] = ((XH32 >> 7) ^ (p256_17 << 8) ^ data[1]) + (XL32 ^ p256_25 ^ p256_01);
            m_state[2] = ((XH32 >> 5) ^ (p256_18 << 5) ^ data[2]) + (XL32 ^ p256_26 ^ p256_02);
            m_state[3] = ((XH32 >> 1) ^ (p256_19 << 5) ^ data[3]) + (XL32 ^ p256_27 ^ p256_03);
            m_state[4] = ((XH32 >> 3) ^ p256_20 ^ data[4]) + (XL32 ^ p256_28 ^ p256_04);
            m_state[5] = ((XH32 << 6) ^ (p256_21 >> 6) ^ data[5]) + (XL32 ^ p256_29 ^ p256_05);
            m_state[6] = ((XH32 >> 4) ^ (p256_22 << 6) ^ data[6]) + (XL32 ^ p256_30 ^ p256_06);
            m_state[7] = ((XH32 >> 11) ^ (p256_23 << 2) ^ data[7]) + (XL32 ^ p256_31 ^ p256_07);

            m_state[8] = ((m_state[4] << 9) | (m_state[4] >> 23)) + (XH32 ^ p256_24 ^ data[8]) + ((XL32 << 8) ^ p256_23 ^ p256_08);
            m_state[9] = ((m_state[5] << 10) | (m_state[5] >> 22)) + (XH32 ^ p256_25 ^ data[9]) + ((XL32 >> 6) ^ p256_16 ^ p256_09);
            m_state[10] = ((m_state[6] << 11) | (m_state[6] >> 21)) + (XH32 ^ p256_26 ^ data[10]) + ((XL32 << 6) ^ p256_17 ^ p256_10);
            m_state[11] = ((m_state[7] << 12) | (m_state[7] >> 20)) + (XH32 ^ p256_27 ^ data[11]) + ((XL32 << 4) ^ p256_18 ^ p256_11);
            m_state[12] = ((m_state[0] << 13) | (m_state[0] >> 19)) + (XH32 ^ p256_28 ^ data[12]) + ((XL32 >> 3) ^ p256_19 ^ p256_12);
            m_state[13] = ((m_state[1] << 14) | (m_state[1] >> 18)) + (XH32 ^ p256_29 ^ data[13]) + ((XL32 >> 4) ^ p256_20 ^ p256_13);
            m_state[14] = ((m_state[2] << 15) | (m_state[2] >> 17)) + (XH32 ^ p256_30 ^ data[14]) + ((XL32 >> 7) ^ p256_21 ^ p256_14);
            m_state[15] = ((m_state[3] << 16) | (m_state[3] >> 16)) + (XH32 ^ p256_31 ^ data[15]) + ((XL32 >> 2) ^ p256_22 ^ p256_15);
        }

        protected override void FinalCompression()
        {
            uint p256_00 = m_state[0] ^ 0xaaaaaaa0;
            uint p256_01 = m_state[1] ^ 0xaaaaaaa1;
            uint p256_02 = m_state[2] ^ 0xaaaaaaa2;
            uint p256_03 = m_state[3] ^ 0xaaaaaaa3;
            uint p256_04 = m_state[4] ^ 0xaaaaaaa4;
            uint p256_05 = m_state[5] ^ 0xaaaaaaa5;
            uint p256_06 = m_state[6] ^ 0xaaaaaaa6;
            uint p256_07 = m_state[7] ^ 0xaaaaaaa7;
            uint p256_08 = m_state[8] ^ 0xaaaaaaa8;
            uint p256_09 = m_state[9] ^ 0xaaaaaaa9;
            uint p256_10 = m_state[10] ^ 0xaaaaaaaa;
            uint p256_11 = m_state[11] ^ 0xaaaaaaab;
            uint p256_12 = m_state[12] ^ 0xaaaaaaac;
            uint p256_13 = m_state[13] ^ 0xaaaaaaad;
            uint p256_14 = m_state[14] ^ 0xaaaaaaae;
            uint p256_15 = m_state[15] ^ 0xaaaaaaaf;

            uint td32_00 = (m_state[0] << 1) | (m_state[0] >> 31);
            uint td32_01 = (m_state[1] << 2) | (m_state[1] >> 30);
            uint td32_02 = (m_state[2] << 3) | (m_state[2] >> 29);
            uint td32_03 = (m_state[3] << 4) | (m_state[3] >> 28);
            uint td32_04 = (m_state[4] << 5) | (m_state[4] >> 27);
            uint td32_05 = (m_state[5] << 6) | (m_state[5] >> 26);
            uint td32_06 = (m_state[6] << 7) | (m_state[6] >> 25);
            uint td32_07 = (m_state[7] << 8) | (m_state[7] >> 24);
            uint td32_08 = (m_state[8] << 9) | (m_state[8] >> 23);
            uint td32_09 = (m_state[9] << 10) | (m_state[9] >> 22);
            uint td32_10 = (m_state[10] << 11) | (m_state[10] >> 21);
            uint td32_11 = (m_state[11] << 12) | (m_state[11] >> 20);
            uint td32_12 = (m_state[12] << 13) | (m_state[12] >> 19);
            uint td32_13 = (m_state[13] << 14) | (m_state[13] >> 18);
            uint td32_14 = (m_state[14] << 15) | (m_state[14] >> 17);
            uint td32_15 = (m_state[15] << 16) | (m_state[15] >> 16);

            uint t256_16 = p256_01 - p256_14;
            uint t256_17 = p256_15 - p256_12;
            uint t256_18 = p256_14 - p256_07;
            uint t256_19 = p256_13 - p256_06;
            uint t256_20 = p256_08 - p256_05;
            uint t256_21 = p256_08 - p256_01;

            uint p256_16 = (p256_05 + t256_18 + p256_10 + p256_13);
            p256_16 = ((p256_16 >> 1) ^ (p256_16 << 3) ^ ((p256_16 << 4) | (p256_16 >> 28)) ^ ((p256_16 << 19) | (p256_16 >> 13))) + 0xaaaaaaa1;
            uint p256_17 = (p256_06 - p256_08 + p256_11 + p256_14 - p256_15);
            p256_17 = ((p256_17 >> 1) ^ (p256_17 << 2) ^ ((p256_17 << 8) | (p256_17 >> 24)) ^ ((p256_17 << 23) | (p256_17 >> 9))) + 0xaaaaaaa2;
            uint p256_18 = (p256_00 + p256_07 + p256_09 + t256_17);
            p256_18 = ((p256_18 >> 2) ^ (p256_18 << 1) ^ ((p256_18 << 12) | (p256_18 >> 20)) ^ ((p256_18 << 25) | (p256_18 >> 7))) + 0xaaaaaaa3;
            uint p256_19 = (p256_00 + t256_21 - p256_10 + p256_13);
            p256_19 = ((p256_19 >> 2) ^ (p256_19 << 2) ^ ((p256_19 << 15) | (p256_19 >> 17)) ^ ((p256_19 << 29) | (p256_19 >> 3))) + 0xaaaaaaa4;
            uint p256_20 = (t256_16 + p256_02 + p256_09 - p256_11);
            p256_20 = ((p256_20 >> 1) ^ p256_20) + 0xaaaaaaa5;
            uint p256_21 = (p256_03 - p256_02 + p256_10 + t256_17);
            p256_21 = ((p256_21 >> 1) ^ (p256_21 << 3) ^ ((p256_21 << 4) | (p256_21 >> 28)) ^ ((p256_21 << 19) | (p256_21 >> 13))) + 0xaaaaaaa6;
            uint p256_22 = (p256_04 - p256_00 - p256_03 - p256_11 + p256_13);
            p256_22 = ((p256_22 >> 1) ^ (p256_22 << 2) ^ ((p256_22 << 8) | (p256_22 >> 24)) ^ ((p256_22 << 23) | (p256_22 >> 9))) + 0xaaaaaaa7;
            uint p256_23 = (t256_16 - p256_04 - p256_05 - p256_12);
            p256_23 = ((p256_23 >> 2) ^ (p256_23 << 1) ^ ((p256_23 << 12) | (p256_23 >> 20)) ^ ((p256_23 << 25) | (p256_23 >> 7))) + 0xaaaaaaa8;
            uint p256_24 = (p256_02 - p256_05 + t256_19 - p256_15);
            p256_24 = ((p256_24 >> 2) ^ (p256_24 << 2) ^ ((p256_24 << 15) | (p256_24 >> 17)) ^ ((p256_24 << 29) | (p256_24 >> 3))) + 0xaaaaaaa9;
            uint p256_25 = (p256_00 - p256_03 + p256_06 + t256_18);
            p256_25 = ((p256_25 >> 1) ^ p256_25) + 0xaaaaaaaa;
            uint p256_26 = (t256_21 - p256_04 - p256_07 + p256_15);
            p256_26 = ((p256_26 >> 1) ^ (p256_26 << 3) ^ ((p256_26 << 4) | (p256_26 >> 28)) ^ ((p256_26 << 19) | (p256_26 >> 13))) + 0xaaaaaaab;
            uint p256_27 = (t256_20 - p256_00 - p256_02 + p256_09);
            p256_27 = ((p256_27 >> 1) ^ (p256_27 << 2) ^ ((p256_27 << 8) | (p256_27 >> 24)) ^ ((p256_27 << 23) | (p256_27 >> 9))) + 0xaaaaaaac;
            uint p256_28 = (p256_01 + p256_03 - p256_06 - p256_09 + p256_10);
            p256_28 = ((p256_28 >> 2) ^ (p256_28 << 1) ^ ((p256_28 << 12) | (p256_28 >> 20)) ^ ((p256_28 << 25) | (p256_28 >> 7))) + 0xaaaaaaad;
            uint p256_29 = (p256_02 + p256_04 + p256_07 + p256_10 + p256_11);
            p256_29 = ((p256_29 >> 2) ^ (p256_29 << 2) ^ ((p256_29 << 15) | (p256_29 >> 17)) ^ ((p256_29 << 29) | (p256_29 >> 3))) + 0xaaaaaaae;
            uint p256_30 = (p256_03 + t256_20 - p256_11 - p256_12);
            p256_14 = ((p256_30 >> 1) ^ p256_30) + 0xaaaaaaaf;
            uint p256_31 = (p256_12 - p256_04 + t256_19 - p256_09);
            p256_15 = ((p256_31 >> 1) ^ (p256_31 << 3) ^ ((p256_31 << 4) | (p256_31 >> 28)) ^ ((p256_31 << 19) | (p256_31 >> 13))) + 0xaaaaaaa0;

            p256_00 = p256_16;
            p256_01 = p256_17;
            p256_02 = p256_18;
            p256_03 = p256_19;
            p256_04 = p256_20;
            p256_05 = p256_21;
            p256_06 = p256_22;
            p256_07 = p256_23;
            p256_08 = p256_24;
            p256_09 = p256_25;
            p256_10 = p256_26;
            p256_11 = p256_27;
            p256_12 = p256_28;
            p256_13 = p256_29;

            p256_16 = ((p256_00 >> 1) ^ (p256_00 << 2) ^ ((p256_00 << 8) | (p256_00 >> 24)) ^ ((p256_00 << 23) | (p256_00 >> 9))) +
                      ((p256_01 >> 2) ^ (p256_01 << 1) ^ ((p256_01 << 12) | (p256_01 >> 20)) ^ ((p256_01 << 25) | (p256_01 >> 7))) +
                      ((p256_02 >> 2) ^ (p256_02 << 2) ^ ((p256_02 << 15) | (p256_02 >> 17)) ^ ((p256_02 << 29) | (p256_02 >> 3))) +
                      ((p256_03 >> 1) ^ (p256_03 << 3) ^ ((p256_03 << 4) | (p256_03 >> 28)) ^ ((p256_03 << 19) | (p256_03 >> 13))) +
                      ((p256_04 >> 1) ^ (p256_04 << 2) ^ ((p256_04 << 8) | (p256_04 >> 24)) ^ ((p256_04 << 23) | (p256_04 >> 9))) +
                      ((p256_05 >> 2) ^ (p256_05 << 1) ^ ((p256_05 << 12) | (p256_05 >> 20)) ^ ((p256_05 << 25) | (p256_05 >> 7))) +
                      ((p256_06 >> 2) ^ (p256_06 << 2) ^ ((p256_06 << 15) | (p256_06 >> 17)) ^ ((p256_06 << 29) | (p256_06 >> 3))) +
                      ((p256_07 >> 1) ^ (p256_07 << 3) ^ ((p256_07 << 4) | (p256_07 >> 28)) ^ ((p256_07 << 19) | (p256_07 >> 13))) +
                      ((p256_08 >> 1) ^ (p256_08 << 2) ^ ((p256_08 << 8) | (p256_08 >> 24)) ^ ((p256_08 << 23) | (p256_08 >> 9))) +
                      ((p256_09 >> 2) ^ (p256_09 << 1) ^ ((p256_09 << 12) | (p256_09 >> 20)) ^ ((p256_09 << 25) | (p256_09 >> 7))) +
                      ((p256_10 >> 2) ^ (p256_10 << 2) ^ ((p256_10 << 15) | (p256_10 >> 17)) ^ ((p256_10 << 29) | (p256_10 >> 3))) +
                      ((p256_11 >> 1) ^ (p256_11 << 3) ^ ((p256_11 << 4) | (p256_11 >> 28)) ^ ((p256_11 << 19) | (p256_11 >> 13))) +
                      ((p256_12 >> 1) ^ (p256_12 << 2) ^ ((p256_12 << 8) | (p256_12 >> 24)) ^ ((p256_12 << 23) | (p256_12 >> 9))) +
                      ((p256_13 >> 2) ^ (p256_13 << 1) ^ ((p256_13 << 12) | (p256_13 >> 20)) ^ ((p256_13 << 25) | (p256_13 >> 7))) +
                      ((p256_14 >> 2) ^ (p256_14 << 2) ^ ((p256_14 << 15) | (p256_14 >> 17)) ^ ((p256_14 << 29) | (p256_14 >> 3))) +
                      ((p256_15 >> 1) ^ (p256_15 << 3) ^ ((p256_15 << 4) | (p256_15 >> 28)) ^ ((p256_15 << 19) | (p256_15 >> 13))) +
                      ((td32_00 + td32_03 - td32_10 + 0x55555550) ^ 0xaaaaaaa7);

            uint XL32 = p256_16;

            p256_17 = ((p256_01 >> 1) ^ (p256_01 << 2) ^ ((p256_01 << 8) | (p256_01 >> 24)) ^ ((p256_01 << 23) | (p256_01 >> 9))) +
                      ((p256_02 >> 2) ^ (p256_02 << 1) ^ ((p256_02 << 12) | (p256_02 >> 20)) ^ ((p256_02 << 25) | (p256_02 >> 7))) +
                      ((p256_03 >> 2) ^ (p256_03 << 2) ^ ((p256_03 << 15) | (p256_03 >> 17)) ^ ((p256_03 << 29) | (p256_03 >> 3))) +
                      ((p256_04 >> 1) ^ (p256_04 << 3) ^ ((p256_04 << 4) | (p256_04 >> 28)) ^ ((p256_04 << 19) | (p256_04 >> 13))) +
                      ((p256_05 >> 1) ^ (p256_05 << 2) ^ ((p256_05 << 8) | (p256_05 >> 24)) ^ ((p256_05 << 23) | (p256_05 >> 9))) +
                      ((p256_06 >> 2) ^ (p256_06 << 1) ^ ((p256_06 << 12) | (p256_06 >> 20)) ^ ((p256_06 << 25) | (p256_06 >> 7))) +
                      ((p256_07 >> 2) ^ (p256_07 << 2) ^ ((p256_07 << 15) | (p256_07 >> 17)) ^ ((p256_07 << 29) | (p256_07 >> 3))) +
                      ((p256_08 >> 1) ^ (p256_08 << 3) ^ ((p256_08 << 4) | (p256_08 >> 28)) ^ ((p256_08 << 19) | (p256_08 >> 13))) +
                      ((p256_09 >> 1) ^ (p256_09 << 2) ^ ((p256_09 << 8) | (p256_09 >> 24)) ^ ((p256_09 << 23) | (p256_09 >> 9))) +
                      ((p256_10 >> 2) ^ (p256_10 << 1) ^ ((p256_10 << 12) | (p256_10 >> 20)) ^ ((p256_10 << 25) | (p256_10 >> 7))) +
                      ((p256_11 >> 2) ^ (p256_11 << 2) ^ ((p256_11 << 15) | (p256_11 >> 17)) ^ ((p256_11 << 29) | (p256_11 >> 3))) +
                      ((p256_12 >> 1) ^ (p256_12 << 3) ^ ((p256_12 << 4) | (p256_12 >> 28)) ^ ((p256_12 << 19) | (p256_12 >> 13))) +
                      ((p256_13 >> 1) ^ (p256_13 << 2) ^ ((p256_13 << 8) | (p256_13 >> 24)) ^ ((p256_13 << 23) | (p256_13 >> 9))) +
                      ((p256_14 >> 2) ^ (p256_14 << 1) ^ ((p256_14 << 12) | (p256_14 >> 20)) ^ ((p256_14 << 25) | (p256_14 >> 7))) +
                      ((p256_15 >> 2) ^ (p256_15 << 2) ^ ((p256_15 << 15) | (p256_15 >> 17)) ^ ((p256_15 << 29) | (p256_15 >> 3))) +
                      ((p256_16 >> 1) ^ (p256_16 << 3) ^ ((p256_16 << 4) | (p256_16 >> 28)) ^ ((p256_16 << 19) | (p256_16 >> 13))) +
                      ((td32_01 + td32_04 - td32_11 + 0x5aaaaaa5) ^ 0xaaaaaaa8);

            XL32 ^= p256_17;
            uint TempEven32 = p256_14 + p256_12 + p256_10 + p256_08 + p256_06 + p256_04 + p256_02;
            uint TempOdd32 = p256_15 + p256_13 + p256_11 + p256_09 + p256_07 + p256_05 + p256_03;

            p256_18 = TempEven32 +
                      ((p256_03 << 3) | (p256_03 >> 29)) +
                      ((p256_05 << 7) | (p256_05 >> 25)) +
                      ((p256_07 << 13) | (p256_07 >> 19)) +
                      ((p256_09 << 16) | (p256_09 >> 16)) +
                      ((p256_11 << 19) | (p256_11 >> 13)) +
                      ((p256_13 << 23) | (p256_13 >> 9)) +
                      ((p256_15 << 27) | (p256_15 >> 5)) +
                      ((p256_16 >> 1) ^ p256_16) +
                      ((p256_17 >> 2) ^ p256_17) +
                      ((td32_02 + td32_05 - td32_12 + 0x5ffffffa) ^ 0xaaaaaaa9);

            XL32 ^= p256_18;

            p256_19 = TempOdd32 +
                      ((p256_04 << 3) | (p256_04 >> 29)) +
                      ((p256_06 << 7) | (p256_06 >> 25)) +
                      ((p256_08 << 13) | (p256_08 >> 19)) + ((p256_10 << 16) | (p256_10 >> 16)) +
                      ((p256_12 << 19) | (p256_12 >> 13)) + ((p256_14 << 23) | (p256_14 >> 9)) +
                      ((p256_16 << 27) | (p256_16 >> 5)) + ((p256_17 >> 1) ^ p256_17) + ((p256_18 >> 2) ^ p256_18) +
                      ((td32_03 + td32_06 - td32_13 + 0x6555554f) ^ 0xaaaaaaaa);

            XL32 ^= p256_19;
            TempEven32 = TempEven32 + p256_16 - p256_02;

            p256_20 = TempEven32 +
                      ((p256_05 << 3) | (p256_05 >> 29)) +
                      ((p256_07 << 7) | (p256_07 >> 25)) +
                      ((p256_09 << 13) | (p256_09 >> 19)) +
                      ((p256_11 << 16) | (p256_11 >> 16)) +
                      ((p256_13 << 19) | (p256_13 >> 13)) +
                      ((p256_15 << 23) | (p256_15 >> 9)) +
                      ((p256_17 << 27) | (p256_17 >> 5)) +
                      ((p256_18 >> 1) ^ p256_18) +
                      ((p256_19 >> 2) ^ p256_19) +
                      ((td32_04 + td32_07 - td32_14 + 0x6aaaaaa4) ^ 0xaaaaaaab);

            XL32 ^= p256_20;
            TempOdd32 = TempOdd32 + p256_17 - p256_03;

            p256_21 = TempOdd32 +
                      ((p256_06 << 3) | (p256_06 >> 29)) +
                      ((p256_08 << 7) | (p256_08 >> 25)) +
                      ((p256_10 << 13) | (p256_10 >> 19)) +
                      ((p256_12 << 16) | (p256_12 >> 16)) +
                      ((p256_14 << 19) | (p256_14 >> 13)) +
                      ((p256_16 << 23) | (p256_16 >> 9)) +
                      ((p256_18 << 27) | (p256_18 >> 5)) +
                      ((p256_19 >> 1) ^ p256_19) +
                      ((p256_20 >> 2) ^ p256_20) +
                      ((td32_05 + td32_08 - td32_15 + 0x6ffffff9) ^ 0xaaaaaaac);

            XL32 ^= p256_21;
            TempEven32 = TempEven32 + p256_18 - p256_04;

            p256_22 = TempEven32 +
                      ((p256_07 << 3) | (p256_07 >> 29)) +
                      ((p256_09 << 7) | (p256_09 >> 25)) +
                      ((p256_11 << 13) | (p256_11 >> 19)) +
                      ((p256_13 << 16) | (p256_13 >> 16)) +
                      ((p256_15 << 19) | (p256_15 >> 13)) +
                      ((p256_17 << 23) | (p256_17 >> 9)) +
                      ((p256_19 << 27) | (p256_19 >> 5)) +
                      ((p256_20 >> 1) ^ p256_20) +
                      ((p256_21 >> 2) ^ p256_21) +
                      ((td32_06 + td32_09 - td32_00 + 0x7555554e) ^ 0xaaaaaaad);

            XL32 ^= p256_22;
            TempOdd32 = TempOdd32 + p256_19 - p256_05;

            p256_23 = TempOdd32 +
                      ((p256_08 << 3) | (p256_08 >> 29)) +
                      ((p256_10 << 7) | (p256_10 >> 25)) +
                      ((p256_12 << 13) | (p256_12 >> 19)) +
                      ((p256_14 << 16) | (p256_14 >> 16)) +
                      ((p256_16 << 19) | (p256_16 >> 13)) +
                      ((p256_18 << 23) | (p256_18 >> 9)) +
                      ((p256_20 << 27) | (p256_20 >> 5)) +
                      ((p256_21 >> 1) ^ p256_21) +
                      ((p256_22 >> 2) ^ p256_22) +
                      ((td32_07 + td32_10 - td32_01 + 0x7aaaaaa3) ^ 0xaaaaaaae);

            XL32 ^= p256_23;
            TempEven32 = TempEven32 + p256_20 - p256_06;

            p256_24 = TempEven32 +
                      ((p256_09 << 3) | (p256_09 >> 29)) +
                      ((p256_11 << 7) | (p256_11 >> 25)) +
                      ((p256_13 << 13) | (p256_13 >> 19)) +
                      ((p256_15 << 16) | (p256_15 >> 16)) +
                      ((p256_17 << 19) | (p256_17 >> 13)) +
                      ((p256_19 << 23) | (p256_19 >> 9)) +
                      ((p256_21 << 27) | (p256_21 >> 5)) +
                      ((p256_22 >> 1) ^ p256_22) +
                      ((p256_23 >> 2) ^ p256_23) +
                      ((td32_08 + td32_11 - td32_02 + 0x7ffffff8) ^ 0xaaaaaaaf);

            uint XH32 = XL32 ^ p256_24;
            TempOdd32 = TempOdd32 + p256_21 - p256_07;

            p256_25 = TempOdd32 +
                      ((p256_10 << 3) | (p256_10 >> 29)) +
                      ((p256_12 << 7) | (p256_12 >> 25)) +
                      ((p256_14 << 13) | (p256_14 >> 19)) +
                      ((p256_16 << 16) | (p256_16 >> 16)) +
                      ((p256_18 << 19) | (p256_18 >> 13)) +
                      ((p256_20 << 23) | (p256_20 >> 9)) +
                      ((p256_22 << 27) | (p256_22 >> 5)) +
                      ((p256_23 >> 1) ^ p256_23) +
                      ((p256_24 >> 2) ^ p256_24) +
                      ((td32_09 + td32_12 - td32_03 + 0x8555554d) ^ 0xaaaaaaa0);

            XH32 ^= p256_25;
            TempEven32 = TempEven32 + p256_22 - p256_08;

            p256_26 = TempEven32 +
                      ((p256_11 << 3) | (p256_11 >> 29)) +
                      ((p256_13 << 7) | (p256_13 >> 25)) +
                      ((p256_15 << 13) | (p256_15 >> 19)) +
                      ((p256_17 << 16) | (p256_17 >> 16)) +
                      ((p256_19 << 19) | (p256_19 >> 13)) +
                      ((p256_21 << 23) | (p256_21 >> 9)) +
                      ((p256_23 << 27) | (p256_23 >> 5)) +
                      ((p256_24 >> 1) ^ p256_24) +
                      ((p256_25 >> 2) ^ p256_25) +
                      ((td32_10 + td32_13 - td32_04 + 0x8aaaaaa2) ^ 0xaaaaaaa1);

            XH32 ^= p256_26;
            TempOdd32 = TempOdd32 + p256_23 - p256_09;

            p256_27 = TempOdd32 +
                      ((p256_12 << 3) | (p256_12 >> 29)) +
                      ((p256_14 << 7) | (p256_14 >> 25)) +
                      ((p256_16 << 13) | (p256_16 >> 19)) +
                      ((p256_18 << 16) | (p256_18 >> 16)) +
                      ((p256_20 << 19) | (p256_20 >> 13)) +
                      ((p256_22 << 23) | (p256_22 >> 9)) +
                      ((p256_24 << 27) | (p256_24 >> 5)) +
                      ((p256_25 >> 1) ^ p256_25) +
                      ((p256_26 >> 2) ^ p256_26) +
                      ((td32_11 + td32_14 - td32_05 + 0x8ffffff7) ^ 0xaaaaaaa2);

            XH32 ^= p256_27;
            TempEven32 = TempEven32 + p256_24 - p256_10;

            p256_28 = TempEven32 +
                      ((p256_13 << 3) | (p256_13 >> 29)) +
                      ((p256_15 << 7) | (p256_15 >> 25)) +
                      ((p256_17 << 13) | (p256_17 >> 19)) +
                      ((p256_19 << 16) | (p256_19 >> 16)) +
                      ((p256_21 << 19) | (p256_21 >> 13)) +
                      ((p256_23 << 23) | (p256_23 >> 9)) +
                      ((p256_25 << 27) | (p256_25 >> 5)) +
                      ((p256_26 >> 1) ^ p256_26) +
                      ((p256_27 >> 2) ^ p256_27) +
                      ((td32_12 + td32_15 - td32_06 + 0x9555554c) ^ 0xaaaaaaa3);

            XH32 ^= p256_28;
            TempOdd32 = TempOdd32 + p256_25 - p256_11;

            p256_29 = TempOdd32 +
                      ((p256_14 << 3) | (p256_14 >> 29)) +
                      ((p256_16 << 7) | (p256_16 >> 25)) +
                      ((p256_18 << 13) | (p256_18 >> 19)) +
                      ((p256_20 << 16) | (p256_20 >> 16)) +
                      ((p256_22 << 19) | (p256_22 >> 13)) +
                      ((p256_24 << 23) | (p256_24 >> 9)) +
                      ((p256_26 << 27) | (p256_26 >> 5)) +
                      ((p256_27 >> 1) ^ p256_27) +
                      ((p256_28 >> 2) ^ p256_28) +
                      ((td32_13 + td32_00 - td32_07 + 0x9aaaaaa1) ^ 0xaaaaaaa4);

            XH32 ^= p256_29;
            TempEven32 = TempEven32 + p256_26 - p256_12;

            p256_30 = TempEven32 +
                      ((p256_15 << 3) | (p256_15 >> 29)) +
                      ((p256_17 << 7) | (p256_17 >> 25)) +
                      ((p256_19 << 13) | (p256_19 >> 19)) +
                      ((p256_21 << 16) | (p256_21 >> 16)) +
                      ((p256_23 << 19) | (p256_23 >> 13)) +
                      ((p256_25 << 23) | (p256_25 >> 9)) +
                      ((p256_27 << 27) | (p256_27 >> 5)) +
                      ((p256_28 >> 1) ^ p256_28) +
                      ((p256_29 >> 2) ^ p256_29) +
                      ((td32_14 + td32_01 - td32_08 + 0x9ffffff6) ^ 0xaaaaaaa5);

            XH32 ^= p256_30;
            TempOdd32 = TempOdd32 + p256_27 - p256_13;

            p256_31 = TempOdd32 +
                      ((p256_16 << 3) | (p256_16 >> 29)) +
                      ((p256_18 << 7) | (p256_18 >> 25)) +
                      ((p256_20 << 13) | (p256_20 >> 19)) +
                      ((p256_22 << 16) | (p256_22 >> 16)) +
                      ((p256_24 << 19) | (p256_24 >> 13)) +
                      ((p256_26 << 23) | (p256_26 >> 9)) +
                      ((p256_28 << 27) | (p256_28 >> 5)) +
                      ((p256_29 >> 1) ^ p256_29) +
                      ((p256_30 >> 2) ^ p256_30) +
                      ((td32_15 + td32_02 - td32_09 + 0xa555554b) ^ 0xaaaaaaa6);

            XH32 ^= p256_31;

            m_state[0] = ((XH32 << 5) ^ (p256_16 >> 5) ^ m_state[0]) + (XL32 ^ p256_24 ^ p256_00);
            m_state[1] = ((XH32 >> 7) ^ (p256_17 << 8) ^ m_state[1]) + (XL32 ^ p256_25 ^ p256_01);
            m_state[2] = ((XH32 >> 5) ^ (p256_18 << 5) ^ m_state[2]) + (XL32 ^ p256_26 ^ p256_02);
            m_state[3] = ((XH32 >> 1) ^ (p256_19 << 5) ^ m_state[3]) + (XL32 ^ p256_27 ^ p256_03);
            m_state[4] = ((XH32 >> 3) ^ p256_20 ^ m_state[4]) + (XL32 ^ p256_28 ^ p256_04);
            m_state[5] = ((XH32 << 6) ^ (p256_21 >> 6) ^ m_state[5]) + (XL32 ^ p256_29 ^ p256_05);
            m_state[6] = ((XH32 >> 4) ^ (p256_22 << 6) ^ m_state[6]) + (XL32 ^ p256_30 ^ p256_06);
            m_state[7] = ((XH32 >> 11) ^ (p256_23 << 2) ^ m_state[7]) + (XL32 ^ p256_31 ^ p256_07);

            m_state[8] = ((m_state[4] << 9) | (m_state[4] >> 23)) + (XH32 ^ p256_24 ^ m_state[8]) + ((XL32 << 8) ^ p256_23 ^ p256_08);
            m_state[9] = ((m_state[5] << 10) | (m_state[5] >> 22)) + (XH32 ^ p256_25 ^ m_state[9]) + ((XL32 >> 6) ^ p256_16 ^ p256_09);
            m_state[10] = ((m_state[6] << 11) | (m_state[6] >> 21)) + (XH32 ^ p256_26 ^ m_state[10]) + ((XL32 << 6) ^ p256_17 ^ p256_10);
            m_state[11] = ((m_state[7] << 12) | (m_state[7] >> 20)) + (XH32 ^ p256_27 ^ m_state[11]) + ((XL32 << 4) ^ p256_18 ^ p256_11);
            m_state[12] = ((m_state[0] << 13) | (m_state[0] >> 19)) + (XH32 ^ p256_28 ^ m_state[12]) + ((XL32 >> 3) ^ p256_19 ^ p256_12);
            m_state[13] = ((m_state[1] << 14) | (m_state[1] >> 18)) + (XH32 ^ p256_29 ^ m_state[13]) + ((XL32 >> 4) ^ p256_20 ^ p256_13);
            m_state[14] = ((m_state[2] << 15) | (m_state[2] >> 17)) + (XH32 ^ p256_30 ^ m_state[14]) + ((XL32 >> 7) ^ p256_21 ^ p256_14);
            m_state[15] = ((m_state[3] << 16) | (m_state[3] >> 16)) + (XH32 ^ p256_31 ^ m_state[15]) + ((XL32 >> 2) ^ p256_22 ^ p256_15);
        }

        protected override byte[] GetResult()
        {
            byte[] result = new byte[HashSize];

            byte[] state = Converters.ConvertUIntsToBytes(m_state);

            if (HashSize == 28)
                Array.Copy(state, 36, result, 0, HashSize);
            else
                Array.Copy(state, 32, result, 0, HashSize);

            return result;
        }

        public override void Initialize()
        {
            m_processed_bytes = 0;

            if (HashSize == 28)
                Array.Copy(s_initial_state_224, m_state, 16);
            else
                Array.Copy(s_initial_state_256, m_state, 16);

            Array.Clear(m_state, 16, 16);

            base.Initialize();
        }
    };

    internal abstract class BlueMidnightWish512Base : BlueMidnightWishBase
    {
        #region Consts
        private static readonly ulong[] s_initial_state_384 = 
            {
                0x0001020304050607, 0x08090a0b0c0d0e0f, 
                0x1011121314151617, 0x18191a1b1c1d1e1f, 
                0x2021222324252627, 0x28292a2b2c2d2e2f, 
                0x3031323334353637, 0x38393a3b3c3d3e3f, 
                0x4041424344454647, 0x48494a4b4c4d4e4f, 
                0x5051525354555657, 0x58595a5b5c5d5e5f, 
                0x6061626364656667, 0x68696a6b6c6d6e6f, 
                0x7071727374757677, 0x78797a7b7c7d7e7f
            };

        private static readonly ulong[] s_initial_state_512 = 
            {
                0x8081828384858687, 0x88898a8b8c8d8e8f, 
                0x9091929394959697, 0x98999a9b9c9d9e9f, 
                0xa0a1a2a3a4a5a6a7, 0xa8a9aaabacadaeaf, 
                0xb0b1b2b3b4b5b6b7, 0xb8b9babbbcbdbebf, 
                0xc0c1c2c3c4c5c6c7, 0xc8c9cacbcccdcecf, 
                0xd0d1d2d3d4d5d6d7, 0xd8d9dadbdcdddedf, 
                0xe0e1e2e3e4e5e6e7, 0xe8e9eaebecedeeef, 
                0xf0f1f2f3f4f5f6f7, 0xf8f9fafbfcfdfeff
            };
        #endregion

        private readonly ulong[] m_state = new ulong[32];

        public BlueMidnightWish512Base(HashSize a_hash_size)
            : base(128, a_hash_size)
        {
            Initialize();
        }

        protected override void TransformBlock(byte[] a_data, int a_index)
        {
            ulong[] data = Converters.ConvertBytesToULongs(a_data, a_index, 128);

            ulong p512_00 = m_state[0] ^ data[0];
            ulong p512_01 = m_state[1] ^ data[1];
            ulong p512_02 = m_state[2] ^ data[2];
            ulong p512_03 = m_state[3] ^ data[3];
            ulong p512_04 = m_state[4] ^ data[4];
            ulong p512_05 = m_state[5] ^ data[5];
            ulong p512_06 = m_state[6] ^ data[6];
            ulong p512_07 = m_state[7] ^ data[7];
            ulong p512_08 = m_state[8] ^ data[8];
            ulong p512_09 = m_state[9] ^ data[9];
            ulong p512_10 = m_state[10] ^ data[10];
            ulong p512_11 = m_state[11] ^ data[11];
            ulong p512_12 = m_state[12] ^ data[12];
            ulong p512_13 = m_state[13] ^ data[13];
            ulong p512_14 = m_state[14] ^ data[14];
            ulong p512_15 = m_state[15] ^ data[15];

            ulong td64_00 = (data[0] << 1) | (data[0] >> 63);
            ulong td64_01 = (data[1] << 2) | (data[1] >> 62);
            ulong td64_02 = (data[2] << 3) | (data[2] >> 61);
            ulong td64_03 = (data[3] << 4) | (data[3] >> 60);
            ulong td64_04 = (data[4] << 5) | (data[4] >> 59);
            ulong td64_05 = (data[5] << 6) | (data[5] >> 58);
            ulong td64_06 = (data[6] << 7) | (data[6] >> 57);
            ulong td64_07 = (data[7] << 8) | (data[7] >> 56);
            ulong td64_08 = (data[8] << 9) | (data[8] >> 55);
            ulong td64_09 = (data[9] << 10) | (data[9] >> 54);
            ulong td64_10 = (data[10] << 11) | (data[10] >> 53);
            ulong td64_11 = (data[11] << 12) | (data[11] >> 52);
            ulong td64_12 = (data[12] << 13) | (data[12] >> 51);
            ulong td64_13 = (data[13] << 14) | (data[13] >> 50);
            ulong td64_14 = (data[14] << 15) | (data[14] >> 49);
            ulong td64_15 = (data[15] << 16) | (data[15] >> 48);

            ulong t512_16 = p512_01 - p512_14;
            ulong t512_17 = p512_15 - p512_12;
            ulong t512_18 = p512_14 - p512_07;
            ulong t512_19 = p512_13 - p512_06;
            ulong t512_20 = p512_08 - p512_05;
            ulong t512_21 = p512_08 - p512_01;

            ulong p512_16 = (p512_05 + t512_18 + p512_10 + p512_13);
            p512_16 = ((p512_16 >> 1) ^ (p512_16 << 3) ^ ((p512_16 << 4) | (p512_16 >> 60)) ^ ((p512_16 << 37) | (p512_16 >> 27))) + m_state[1];
            ulong p512_17 = (p512_06 - p512_08 + p512_11 + p512_14 - p512_15);
            p512_17 = ((p512_17 >> 1) ^ (p512_17 << 2) ^ ((p512_17 << 13) | (p512_17 >> 51)) ^ ((p512_17 << 43) | (p512_17 >> 21))) + m_state[2];
            ulong p512_18 = (p512_00 + p512_07 + p512_09 + t512_17);
            p512_18 = ((p512_18 >> 2) ^ (p512_18 << 1) ^ ((p512_18 << 19) | (p512_18 >> 45)) ^ ((p512_18 << 53) | (p512_18 >> 11))) + m_state[3];
            ulong p512_19 = (p512_00 + t512_21 - p512_10 + p512_13);
            p512_19 = ((p512_19 >> 2) ^ (p512_19 << 2) ^ ((p512_19 << 28) | (p512_19 >> 36)) ^ ((p512_19 << 59) | (p512_19 >> 5))) + m_state[4];
            ulong p512_20 = (t512_16 + p512_02 + p512_09 - p512_11);
            p512_20 = ((p512_20 >> 1) ^ p512_20) + m_state[5];
            ulong p512_21 = (p512_03 - p512_02 + p512_10 + t512_17);
            p512_21 = ((p512_21 >> 1) ^ (p512_21 << 3) ^ ((p512_21 << 4) | (p512_21 >> 60)) ^ ((p512_21 << 37) | (p512_21 >> 27))) + m_state[6];
            ulong p512_22 = (p512_04 - p512_00 - p512_03 - p512_11 + p512_13);
            p512_22 = ((p512_22 >> 1) ^ (p512_22 << 2) ^ ((p512_22 << 13) | (p512_22 >> 51)) ^ ((p512_22 << 43) | (p512_22 >> 21))) + m_state[7];
            ulong p512_23 = (t512_16 - p512_04 - p512_05 - p512_12);
            p512_23 = ((p512_23 >> 2) ^ (p512_23 << 1) ^ ((p512_23 << 19) | (p512_23 >> 45)) ^ ((p512_23 << 53) | (p512_23 >> 11))) + m_state[8];
            ulong p512_24 = (p512_02 - p512_05 + t512_19 - p512_15);
            p512_24 = ((p512_24 >> 2) ^ (p512_24 << 2) ^ ((p512_24 << 28) | (p512_24 >> 36)) ^ ((p512_24 << 59) | (p512_24 >> 5))) + m_state[9];
            ulong p512_25 = (p512_00 - p512_03 + p512_06 + t512_18);
            p512_25 = ((p512_25 >> 1) ^ p512_25) + m_state[10];
            ulong p512_26 = (t512_21 - p512_04 - p512_07 + p512_15);
            p512_26 = ((p512_26 >> 1) ^ (p512_26 << 3) ^ ((p512_26 << 4) | (p512_26 >> 60)) ^ ((p512_26 << 37) | (p512_26 >> 27))) + m_state[11];
            ulong p512_27 = (t512_20 - p512_00 - p512_02 + p512_09);
            p512_27 = ((p512_27 >> 1) ^ (p512_27 << 2) ^ ((p512_27 << 13) | (p512_27 >> 51)) ^ ((p512_27 << 43) | (p512_27 >> 21))) + m_state[12];
            ulong p512_28 = (p512_01 + p512_03 - p512_06 - p512_09 + p512_10);
            p512_28 = ((p512_28 >> 2) ^ (p512_28 << 1) ^ ((p512_28 << 19) | (p512_28 >> 45)) ^ ((p512_28 << 53) | (p512_28 >> 11))) + m_state[13];
            ulong p512_29 = (p512_02 + p512_04 + p512_07 + p512_10 + p512_11);
            p512_29 = ((p512_29 >> 2) ^ (p512_29 << 2) ^ ((p512_29 << 28) | (p512_29 >> 36)) ^ ((p512_29 << 59) | (p512_29 >> 5))) + m_state[14];
            ulong p512_30 = (p512_03 + t512_20 - p512_11 - p512_12);
            p512_14 = ((p512_30 >> 1) ^ p512_30) + m_state[15];
            ulong p512_31 = (p512_12 - p512_04 + t512_19 - p512_09);
            p512_15 = ((p512_31 >> 1) ^ (p512_31 << 3) ^ ((p512_31 << 4) | (p512_31 >> 60)) ^ ((p512_31 << 37) | (p512_31 >> 27))) + m_state[0];

            p512_00 = p512_16;
            p512_01 = p512_17;
            p512_02 = p512_18;
            p512_03 = p512_19;
            p512_04 = p512_20;
            p512_05 = p512_21;
            p512_06 = p512_22;
            p512_07 = p512_23;
            p512_08 = p512_24;
            p512_09 = p512_25;
            p512_10 = p512_26;
            p512_11 = p512_27;
            p512_12 = p512_28;
            p512_13 = p512_29;

            p512_16 = ((p512_00 >> 1) ^ (p512_00 << 2) ^ ((p512_00 << 13) | (p512_00 >> 51)) ^ ((p512_00 << 43) | (p512_00 >> 21))) +
                      ((p512_01 >> 2) ^ (p512_01 << 1) ^ ((p512_01 << 19) | (p512_01 >> 45)) ^ ((p512_01 << 53) | (p512_01 >> 11))) +
                      ((p512_02 >> 2) ^ (p512_02 << 2) ^ ((p512_02 << 28) | (p512_02 >> 36)) ^ ((p512_02 << 59) | (p512_02 >> 5))) +
                      ((p512_03 >> 1) ^ (p512_03 << 3) ^ ((p512_03 << 4) | (p512_03 >> 60)) ^ ((p512_03 << 37) | (p512_03 >> 27))) +
                      ((p512_04 >> 1) ^ (p512_04 << 2) ^ ((p512_04 << 13) | (p512_04 >> 51)) ^ ((p512_04 << 43) | (p512_04 >> 21))) +
                      ((p512_05 >> 2) ^ (p512_05 << 1) ^ ((p512_05 << 19) | (p512_05 >> 45)) ^ ((p512_05 << 53) | (p512_05 >> 11))) +
                      ((p512_06 >> 2) ^ (p512_06 << 2) ^ ((p512_06 << 28) | (p512_06 >> 36)) ^ ((p512_06 << 59) | (p512_06 >> 5))) +
                      ((p512_07 >> 1) ^ (p512_07 << 3) ^ ((p512_07 << 4) | (p512_07 >> 60)) ^ ((p512_07 << 37) | (p512_07 >> 27))) +
                      ((p512_08 >> 1) ^ (p512_08 << 2) ^ ((p512_08 << 13) | (p512_08 >> 51)) ^ ((p512_08 << 43) | (p512_08 >> 21))) +
                      ((p512_09 >> 2) ^ (p512_09 << 1) ^ ((p512_09 << 19) | (p512_09 >> 45)) ^ ((p512_09 << 53) | (p512_09 >> 11))) +
                      ((p512_10 >> 2) ^ (p512_10 << 2) ^ ((p512_10 << 28) | (p512_10 >> 36)) ^ ((p512_10 << 59) | (p512_10 >> 5))) +
                      ((p512_11 >> 1) ^ (p512_11 << 3) ^ ((p512_11 << 4) | (p512_11 >> 60)) ^ ((p512_11 << 37) | (p512_11 >> 27))) +
                      ((p512_12 >> 1) ^ (p512_12 << 2) ^ ((p512_12 << 13) | (p512_12 >> 51)) ^ ((p512_12 << 43) | (p512_12 >> 21))) +
                      ((p512_13 >> 2) ^ (p512_13 << 1) ^ ((p512_13 << 19) | (p512_13 >> 45)) ^ ((p512_13 << 53) | (p512_13 >> 11))) +
                      ((p512_14 >> 2) ^ (p512_14 << 2) ^ ((p512_14 << 28) | (p512_14 >> 36)) ^ ((p512_14 << 59) | (p512_14 >> 5))) +
                      ((p512_15 >> 1) ^ (p512_15 << 3) ^ ((p512_15 << 4) | (p512_15 >> 60)) ^ ((p512_15 << 37) | (p512_15 >> 27))) +
                      ((td64_00 + td64_03 - td64_10 + 0x5555555555555550) ^ m_state[7]);

            ulong XL64 = p512_16;

            p512_17 = ((p512_01 >> 1) ^ (p512_01 << 2) ^ ((p512_01 << 13) | (p512_01 >> 51)) ^ ((p512_01 << 43) | (p512_01 >> 21))) +
                      ((p512_02 >> 2) ^ (p512_02 << 1) ^ ((p512_02 << 19) | (p512_02 >> 45)) ^ ((p512_02 << 53) | (p512_02 >> 11))) +
                      ((p512_03 >> 2) ^ (p512_03 << 2) ^ ((p512_03 << 28) | (p512_03 >> 36)) ^ ((p512_03 << 59) | (p512_03 >> 5))) +
                      ((p512_04 >> 1) ^ (p512_04 << 3) ^ ((p512_04 << 4) | (p512_04 >> 60)) ^ ((p512_04 << 37) | (p512_04 >> 27))) +
                      ((p512_05 >> 1) ^ (p512_05 << 2) ^ ((p512_05 << 13) | (p512_05 >> 51)) ^ ((p512_05 << 43) | (p512_05 >> 21))) +
                      ((p512_06 >> 2) ^ (p512_06 << 1) ^ ((p512_06 << 19) | (p512_06 >> 45)) ^ ((p512_06 << 53) | (p512_06 >> 11))) +
                      ((p512_07 >> 2) ^ (p512_07 << 2) ^ ((p512_07 << 28) | (p512_07 >> 36)) ^ ((p512_07 << 59) | (p512_07 >> 5))) +
                      ((p512_08 >> 1) ^ (p512_08 << 3) ^ ((p512_08 << 4) | (p512_08 >> 60)) ^ ((p512_08 << 37) | (p512_08 >> 27))) +
                      ((p512_09 >> 1) ^ (p512_09 << 2) ^ ((p512_09 << 13) | (p512_09 >> 51)) ^ ((p512_09 << 43) | (p512_09 >> 21))) +
                      ((p512_10 >> 2) ^ (p512_10 << 1) ^ ((p512_10 << 19) | (p512_10 >> 45)) ^ ((p512_10 << 53) | (p512_10 >> 11))) +
                      ((p512_11 >> 2) ^ (p512_11 << 2) ^ ((p512_11 << 28) | (p512_11 >> 36)) ^ ((p512_11 << 59) | (p512_11 >> 5))) +
                      ((p512_12 >> 1) ^ (p512_12 << 3) ^ ((p512_12 << 4) | (p512_12 >> 60)) ^ ((p512_12 << 37) | (p512_12 >> 27))) +
                      ((p512_13 >> 1) ^ (p512_13 << 2) ^ ((p512_13 << 13) | (p512_13 >> 51)) ^ ((p512_13 << 43) | (p512_13 >> 21))) +
                      ((p512_14 >> 2) ^ (p512_14 << 1) ^ ((p512_14 << 19) | (p512_14 >> 45)) ^ ((p512_14 << 53) | (p512_14 >> 11))) +
                      ((p512_15 >> 2) ^ (p512_15 << 2) ^ ((p512_15 << 28) | (p512_15 >> 36)) ^ ((p512_15 << 59) | (p512_15 >> 5))) +
                      ((p512_16 >> 1) ^ (p512_16 << 3) ^ ((p512_16 << 4) | (p512_16 >> 60)) ^ ((p512_16 << 37) | (p512_16 >> 27))) +
                      ((td64_01 + td64_04 - td64_11 + 0x5aaaaaaaaaaaaaa5) ^ m_state[8]);

            XL64 ^= p512_17;
            ulong TempEven64 = p512_14 + p512_12 + p512_10 + p512_08 + p512_06 + p512_04 + p512_02;
            ulong TempOdd64 = p512_15 + p512_13 + p512_11 + p512_09 + p512_07 + p512_05 + p512_03;

            p512_18 = TempEven64 +
                      ((p512_03 << 5) | (p512_03 >> 59)) +
                      ((p512_05 << 11) | (p512_05 >> 53)) +
                      ((p512_07 << 27) | (p512_07 >> 37)) +
                      ((p512_09 << 32) | (p512_09 >> 32)) +
                      ((p512_11 << 37) | (p512_11 >> 27)) +
                      ((p512_13 << 43) | (p512_13 >> 21)) +
                      ((p512_15 << 53) | (p512_15 >> 11)) +
                      ((p512_16 >> 1) ^ p512_16) +
                      ((p512_17 >> 2) ^ p512_17) +
                      ((td64_02 + td64_05 - td64_12 + 0x5ffffffffffffffa) ^ m_state[9]);

            XL64 ^= p512_18;

            p512_19 = TempOdd64 +
                      ((p512_04 << 5) | (p512_04 >> 59)) +
                      ((p512_06 << 11) | (p512_06 >> 53)) +
                      ((p512_08 << 27) | (p512_08 >> 37)) +
                      ((p512_10 << 32) | (p512_10 >> 32)) +
                      ((p512_12 << 37) | (p512_12 >> 27)) +
                      ((p512_14 << 43) | (p512_14 >> 21)) +
                      ((p512_16 << 53) | (p512_16 >> 11)) +
                      ((p512_17 >> 1) ^ p512_17) +
                      ((p512_18 >> 2) ^ p512_18) +
                      ((td64_03 + td64_06 - td64_13 + 0x655555555555554f) ^ m_state[10]);

            XL64 ^= p512_19;
            TempEven64 = TempEven64 + p512_16 - p512_02;

            p512_20 = TempEven64 +
                      ((p512_05 << 5) | (p512_05 >> 59)) +
                      ((p512_07 << 11) | (p512_07 >> 53)) +
                      ((p512_09 << 27) | (p512_09 >> 37)) +
                      ((p512_11 << 32) | (p512_11 >> 32)) +
                      ((p512_13 << 37) | (p512_13 >> 27)) +
                      ((p512_15 << 43) | (p512_15 >> 21)) +
                      ((p512_17 << 53) | (p512_17 >> 11)) +
                      ((p512_18 >> 1) ^ p512_18) +
                      ((p512_19 >> 2) ^ p512_19) +
                      ((td64_04 + td64_07 - td64_14 + 0x6aaaaaaaaaaaaaa4) ^ m_state[11]);

            XL64 ^= p512_20;
            TempOdd64 = TempOdd64 + p512_17 - p512_03;

            p512_21 = TempOdd64 +
                      ((p512_06 << 5) | (p512_06 >> 59)) +
                      ((p512_08 << 11) | (p512_08 >> 53)) +
                      ((p512_10 << 27) | (p512_10 >> 37)) +
                      ((p512_12 << 32) | (p512_12 >> 32)) +
                      ((p512_14 << 37) | (p512_14 >> 27)) +
                      ((p512_16 << 43) | (p512_16 >> 21)) +
                      ((p512_18 << 53) | (p512_18 >> 11)) +
                      ((p512_19 >> 1) ^ p512_19) +
                      ((p512_20 >> 2) ^ p512_20) +
                      ((td64_05 + td64_08 - td64_15 + 0x6ffffffffffffff9) ^ m_state[12]);

            XL64 ^= p512_21;
            TempEven64 += p512_18; TempEven64 -= p512_04;

            p512_22 = TempEven64 +
                      ((p512_07 << 5) | (p512_07 >> 59)) +
                      ((p512_09 << 11) | (p512_09 >> 53)) +
                      ((p512_11 << 27) | (p512_11 >> 37)) +
                      ((p512_13 << 32) | (p512_13 >> 32)) +
                      ((p512_15 << 37) | (p512_15 >> 27)) +
                      ((p512_17 << 43) | (p512_17 >> 21)) +
                      ((p512_19 << 53) | (p512_19 >> 11)) +
                      ((p512_20 >> 1) ^ p512_20) +
                      ((p512_21 >> 2) ^ p512_21) +
                      ((td64_06 + td64_09 - td64_00 + 0x755555555555554e) ^ m_state[13]);

            XL64 ^= p512_22;
            TempOdd64 += p512_19; TempOdd64 -= p512_05;

            p512_23 = TempOdd64 +
                      ((p512_08 << 5) | (p512_08 >> 59)) +
                      ((p512_10 << 11) | (p512_10 >> 53)) +
                      ((p512_12 << 27) | (p512_12 >> 37)) +
                      ((p512_14 << 32) | (p512_14 >> 32)) +
                      ((p512_16 << 37) | (p512_16 >> 27)) +
                      ((p512_18 << 43) | (p512_18 >> 21)) +
                      ((p512_20 << 53) | (p512_20 >> 11)) +
                      ((p512_21 >> 1) ^ p512_21) +
                      ((p512_22 >> 2) ^ p512_22) +
                      ((td64_07 + td64_10 - td64_01 + 0x7aaaaaaaaaaaaaa3) ^ m_state[14]);

            XL64 ^= p512_23;
            TempEven64 += p512_20; TempEven64 -= p512_06;

            p512_24 = TempEven64 +
                      ((p512_09 << 5) | (p512_09 >> 59)) +
                      ((p512_11 << 11) | (p512_11 >> 53)) +
                      ((p512_13 << 27) | (p512_13 >> 37)) +
                      ((p512_15 << 32) | (p512_15 >> 32)) +
                      ((p512_17 << 37) | (p512_17 >> 27)) +
                      ((p512_19 << 43) | (p512_19 >> 21)) +
                      ((p512_21 << 53) | (p512_21 >> 11)) +
                      ((p512_22 >> 1) ^ p512_22) +
                      ((p512_23 >> 2) ^ p512_23) +
                      ((td64_08 + td64_11 - td64_02 + 0x7ffffffffffffff8) ^ m_state[15]);

            ulong XH64 = XL64 ^ p512_24;
            TempOdd64 += p512_21; TempOdd64 -= p512_07;

            p512_25 = TempOdd64 +
                      ((p512_10 << 5) | (p512_10 >> 59)) +
                      ((p512_12 << 11) | (p512_12 >> 53)) +
                      ((p512_14 << 27) | (p512_14 >> 37)) +
                      ((p512_16 << 32) | (p512_16 >> 32)) +
                      ((p512_18 << 37) | (p512_18 >> 27)) +
                      ((p512_20 << 43) | (p512_20 >> 21)) +
                      ((p512_22 << 53) | (p512_22 >> 11)) +
                      ((p512_23 >> 1) ^ p512_23) +
                      ((p512_24 >> 2) ^ p512_24) +
                      ((td64_09 + td64_12 - td64_03 + 0x855555555555554d) ^ m_state[0]);

            XH64 ^= p512_25;
            TempEven64 += p512_22; TempEven64 -= p512_08;

            p512_26 = TempEven64 +
                      ((p512_11 << 5) | (p512_11 >> 59)) +
                      ((p512_13 << 11) | (p512_13 >> 53)) +
                      ((p512_15 << 27) | (p512_15 >> 37)) +
                      ((p512_17 << 32) | (p512_17 >> 32)) +
                      ((p512_19 << 37) | (p512_19 >> 27)) +
                      ((p512_21 << 43) | (p512_21 >> 21)) +
                      ((p512_23 << 53) | (p512_23 >> 11)) +
                      ((p512_24 >> 1) ^ p512_24) +
                      ((p512_25 >> 2) ^ p512_25) +
                      ((td64_10 + td64_13 - td64_04 + 0x8aaaaaaaaaaaaaa2) ^ m_state[1]);

            XH64 ^= p512_26;
            TempOdd64 += p512_23; TempOdd64 -= p512_09;

            p512_27 = TempOdd64 +
                      ((p512_12 << 5) | (p512_12 >> 59)) +
                      ((p512_14 << 11) | (p512_14 >> 53)) +
                      ((p512_16 << 27) | (p512_16 >> 37)) +
                      ((p512_18 << 32) | (p512_18 >> 32)) +
                      ((p512_20 << 37) | (p512_20 >> 27)) +
                      ((p512_22 << 43) | (p512_22 >> 21)) +
                      ((p512_24 << 53) | (p512_24 >> 11)) +
                      ((p512_25 >> 1) ^ p512_25) +
                      ((p512_26 >> 2) ^ p512_26) +
                      ((td64_11 + td64_14 - td64_05 + 0x8ffffffffffffff7) ^ m_state[2]);

            XH64 ^= p512_27;
            TempEven64 += p512_24; TempEven64 -= p512_10;

            p512_28 = TempEven64 +
                      ((p512_13 << 5) | (p512_13 >> 59)) +
                      ((p512_15 << 11) | (p512_15 >> 53)) +
                      ((p512_17 << 27) | (p512_17 >> 37)) +
                      ((p512_19 << 32) | (p512_19 >> 32)) +
                      ((p512_21 << 37) | (p512_21 >> 27)) +
                      ((p512_23 << 43) | (p512_23 >> 21)) +
                      ((p512_25 << 53) | (p512_25 >> 11)) +
                      ((p512_26 >> 1) ^ p512_26) +
                      ((p512_27 >> 2) ^ p512_27) +
                      ((td64_12 + td64_15 - td64_06 + 0x955555555555554c) ^ m_state[3]);

            XH64 ^= p512_28;
            TempOdd64 += p512_25; TempOdd64 -= p512_11;

            p512_29 = TempOdd64 +
                      ((p512_14 << 5) | (p512_14 >> 59)) +
                      ((p512_16 << 11) | (p512_16 >> 53)) +
                      ((p512_18 << 27) | (p512_18 >> 37)) +
                      ((p512_20 << 32) | (p512_20 >> 32)) +
                      ((p512_22 << 37) | (p512_22 >> 27)) +
                      ((p512_24 << 43) | (p512_24 >> 21)) +
                      ((p512_26 << 53) | (p512_26 >> 11)) +
                      ((p512_27 >> 1) ^ p512_27) +
                      ((p512_28 >> 2) ^ p512_28) +
                      ((td64_13 + td64_00 - td64_07 + 0x9aaaaaaaaaaaaaa1) ^ m_state[4]);

            XH64 ^= p512_29;
            TempEven64 += p512_26; TempEven64 -= p512_12;

            p512_30 = TempEven64 +
                      ((p512_15 << 5) | (p512_15 >> 59)) +
                      ((p512_17 << 11) | (p512_17 >> 53)) +
                      ((p512_19 << 27) | (p512_19 >> 37)) +
                      ((p512_21 << 32) | (p512_21 >> 32)) +
                      ((p512_23 << 37) | (p512_23 >> 27)) +
                      ((p512_25 << 43) | (p512_25 >> 21)) +
                      ((p512_27 << 53) | (p512_27 >> 11)) +
                      ((p512_28 >> 1) ^ p512_28) +
                      ((p512_29 >> 2) ^ p512_29) +
                      ((td64_14 + td64_01 - td64_08 + 0x9ffffffffffffff6) ^ m_state[5]);

            XH64 ^= p512_30;
            TempOdd64 += p512_27; TempOdd64 -= p512_13;

            p512_31 = TempOdd64 +
                      ((p512_16 << 5) | (p512_16 >> 59)) +
                      ((p512_18 << 11) | (p512_18 >> 53)) +
                      ((p512_20 << 27) | (p512_20 >> 37)) +
                      ((p512_22 << 32) | (p512_22 >> 32)) +
                      ((p512_24 << 37) | (p512_24 >> 27)) +
                      ((p512_26 << 43) | (p512_26 >> 21)) +
                      ((p512_28 << 53) | (p512_28 >> 11)) +
                      ((p512_29 >> 1) ^ p512_29) +
                      ((p512_30 >> 2) ^ p512_30) +
                      ((td64_15 + td64_02 - td64_09 + 0xa55555555555554b) ^ m_state[6]);

            XH64 ^= p512_31;

            m_state[0] = ((XH64 << 5) ^ (p512_16 >> 5) ^ data[0]) + (XL64 ^ p512_24 ^ p512_00);
            m_state[1] = ((XH64 >> 7) ^ (p512_17 << 8) ^ data[1]) + (XL64 ^ p512_25 ^ p512_01);
            m_state[2] = ((XH64 >> 5) ^ (p512_18 << 5) ^ data[2]) + (XL64 ^ p512_26 ^ p512_02);
            m_state[3] = ((XH64 >> 1) ^ (p512_19 << 5) ^ data[3]) + (XL64 ^ p512_27 ^ p512_03);
            m_state[4] = ((XH64 >> 3) ^ p512_20 ^ data[4]) + (XL64 ^ p512_28 ^ p512_04);
            m_state[5] = ((XH64 << 6) ^ (p512_21 >> 6) ^ data[5]) + (XL64 ^ p512_29 ^ p512_05);
            m_state[6] = ((XH64 >> 4) ^ (p512_22 << 6) ^ data[6]) + (XL64 ^ p512_30 ^ p512_06);
            m_state[7] = ((XH64 >> 11) ^ (p512_23 << 2) ^ data[7]) + (XL64 ^ p512_31 ^ p512_07);

            m_state[8] = ((m_state[4] << 9) | (m_state[4] >> 55)) + (XH64 ^ p512_24 ^ data[8]) + ((XL64 << 8) ^ p512_23 ^ p512_08);
            m_state[9] = ((m_state[5] << 10) | (m_state[5] >> 54)) + (XH64 ^ p512_25 ^ data[9]) + ((XL64 >> 6) ^ p512_16 ^ p512_09);
            m_state[10] = ((m_state[6] << 11) | (m_state[6] >> 53)) + (XH64 ^ p512_26 ^ data[10]) + ((XL64 << 6) ^ p512_17 ^ p512_10);
            m_state[11] = ((m_state[7] << 12) | (m_state[7] >> 52)) + (XH64 ^ p512_27 ^ data[11]) + ((XL64 << 4) ^ p512_18 ^ p512_11);
            m_state[12] = ((m_state[0] << 13) | (m_state[0] >> 51)) + (XH64 ^ p512_28 ^ data[12]) + ((XL64 >> 3) ^ p512_19 ^ p512_12);
            m_state[13] = ((m_state[1] << 14) | (m_state[1] >> 50)) + (XH64 ^ p512_29 ^ data[13]) + ((XL64 >> 4) ^ p512_20 ^ p512_13);
            m_state[14] = ((m_state[2] << 15) | (m_state[2] >> 49)) + (XH64 ^ p512_30 ^ data[14]) + ((XL64 >> 7) ^ p512_21 ^ p512_14);
            m_state[15] = ((m_state[3] << 16) | (m_state[3] >> 48)) + (XH64 ^ p512_31 ^ data[15]) + ((XL64 >> 2) ^ p512_22 ^ p512_15);
        }

        protected override void FinalCompression()
        {
            ulong p512_00 = m_state[0] ^ 0xaaaaaaaaaaaaaaa0;
            ulong p512_01 = m_state[1] ^ 0xaaaaaaaaaaaaaaa1;
            ulong p512_02 = m_state[2] ^ 0xaaaaaaaaaaaaaaa2;
            ulong p512_03 = m_state[3] ^ 0xaaaaaaaaaaaaaaa3;
            ulong p512_04 = m_state[4] ^ 0xaaaaaaaaaaaaaaa4;
            ulong p512_05 = m_state[5] ^ 0xaaaaaaaaaaaaaaa5;
            ulong p512_06 = m_state[6] ^ 0xaaaaaaaaaaaaaaa6;
            ulong p512_07 = m_state[7] ^ 0xaaaaaaaaaaaaaaa7;
            ulong p512_08 = m_state[8] ^ 0xaaaaaaaaaaaaaaa8;
            ulong p512_09 = m_state[9] ^ 0xaaaaaaaaaaaaaaa9;
            ulong p512_10 = m_state[10] ^ 0xaaaaaaaaaaaaaaaa;
            ulong p512_11 = m_state[11] ^ 0xaaaaaaaaaaaaaaab;
            ulong p512_12 = m_state[12] ^ 0xaaaaaaaaaaaaaaac;
            ulong p512_13 = m_state[13] ^ 0xaaaaaaaaaaaaaaad;
            ulong p512_14 = m_state[14] ^ 0xaaaaaaaaaaaaaaae;
            ulong p512_15 = m_state[15] ^ 0xaaaaaaaaaaaaaaaf;

            ulong td64_00 = (m_state[0] << 1) | (m_state[0] >> 63);
            ulong td64_01 = (m_state[1] << 2) | (m_state[1] >> 62);
            ulong td64_02 = (m_state[2] << 3) | (m_state[2] >> 61);
            ulong td64_03 = (m_state[3] << 4) | (m_state[3] >> 60);
            ulong td64_04 = (m_state[4] << 5) | (m_state[4] >> 59);
            ulong td64_05 = (m_state[5] << 6) | (m_state[5] >> 58);
            ulong td64_06 = (m_state[6] << 7) | (m_state[6] >> 57);
            ulong td64_07 = (m_state[7] << 8) | (m_state[7] >> 56);
            ulong td64_08 = (m_state[8] << 9) | (m_state[8] >> 55);
            ulong td64_09 = (m_state[9] << 10) | (m_state[9] >> 54);
            ulong td64_10 = (m_state[10] << 11) | (m_state[10] >> 53);
            ulong td64_11 = (m_state[11] << 12) | (m_state[11] >> 52);
            ulong td64_12 = (m_state[12] << 13) | (m_state[12] >> 51);
            ulong td64_13 = (m_state[13] << 14) | (m_state[13] >> 50);
            ulong td64_14 = (m_state[14] << 15) | (m_state[14] >> 49);
            ulong td64_15 = (m_state[15] << 16) | (m_state[15] >> 48);

            ulong t512_16 = p512_01 - p512_14;
            ulong t512_17 = p512_15 - p512_12;
            ulong t512_18 = p512_14 - p512_07;
            ulong t512_19 = p512_13 - p512_06;
            ulong t512_20 = p512_08 - p512_05;
            ulong t512_21 = p512_08 - p512_01;

            ulong p512_16 = (p512_05 + t512_18 + p512_10 + p512_13);
            p512_16 = ((p512_16 >> 1) ^ (p512_16 << 3) ^ ((p512_16 << 4) | (p512_16 >> 60)) ^ ((p512_16 << 37) | (p512_16 >> 27))) + 0xaaaaaaaaaaaaaaa1;
            ulong p512_17 = (p512_06 - p512_08 + p512_11 + p512_14 - p512_15);
            p512_17 = ((p512_17 >> 1) ^ (p512_17 << 2) ^ ((p512_17 << 13) | (p512_17 >> 51)) ^ ((p512_17 << 43) | (p512_17 >> 21))) + 0xaaaaaaaaaaaaaaa2;
            ulong p512_18 = (p512_00 + p512_07 + p512_09 + t512_17);
            p512_18 = ((p512_18 >> 2) ^ (p512_18 << 1) ^ ((p512_18 << 19) | (p512_18 >> 45)) ^ ((p512_18 << 53) | (p512_18 >> 11))) + 0xaaaaaaaaaaaaaaa3;
            ulong p512_19 = (p512_00 + t512_21 - p512_10 + p512_13);
            p512_19 = ((p512_19 >> 2) ^ (p512_19 << 2) ^ ((p512_19 << 28) | (p512_19 >> 36)) ^ ((p512_19 << 59) | (p512_19 >> 5))) + 0xaaaaaaaaaaaaaaa4;
            ulong p512_20 = (t512_16 + p512_02 + p512_09 - p512_11);
            p512_20 = ((p512_20 >> 1) ^ p512_20) + 0xaaaaaaaaaaaaaaa5;
            ulong p512_21 = (p512_03 - p512_02 + p512_10 + t512_17);
            p512_21 = ((p512_21 >> 1) ^ (p512_21 << 3) ^ ((p512_21 << 4) | (p512_21 >> 60)) ^ ((p512_21 << 37) | (p512_21 >> 27))) + 0xaaaaaaaaaaaaaaa6;
            ulong p512_22 = (p512_04 - p512_00 - p512_03 - p512_11 + p512_13);
            p512_22 = ((p512_22 >> 1) ^ (p512_22 << 2) ^ ((p512_22 << 13) | (p512_22 >> 51)) ^ ((p512_22 << 43) | (p512_22 >> 21))) + 0xaaaaaaaaaaaaaaa7;
            ulong p512_23 = (t512_16 - p512_04 - p512_05 - p512_12);
            p512_23 = ((p512_23 >> 2) ^ (p512_23 << 1) ^ ((p512_23 << 19) | (p512_23 >> 45)) ^ ((p512_23 << 53) | (p512_23 >> 11))) + 0xaaaaaaaaaaaaaaa8;
            ulong p512_24 = (p512_02 - p512_05 + t512_19 - p512_15);
            p512_24 = ((p512_24 >> 2) ^ (p512_24 << 2) ^ ((p512_24 << 28) | (p512_24 >> 36)) ^ ((p512_24 << 59) | (p512_24 >> 5))) + 0xaaaaaaaaaaaaaaa9;
            ulong p512_25 = (p512_00 - p512_03 + p512_06 + t512_18);
            p512_25 = ((p512_25 >> 1) ^ p512_25) + 0xaaaaaaaaaaaaaaaa;
            ulong p512_26 = (t512_21 - p512_04 - p512_07 + p512_15);
            p512_26 = ((p512_26 >> 1) ^ (p512_26 << 3) ^ ((p512_26 << 4) | (p512_26 >> 60)) ^ ((p512_26 << 37) | (p512_26 >> 27))) + 0xaaaaaaaaaaaaaaab;
            ulong p512_27 = (t512_20 - p512_00 - p512_02 + p512_09);
            p512_27 = ((p512_27 >> 1) ^ (p512_27 << 2) ^ ((p512_27 << 13) | (p512_27 >> 51)) ^ ((p512_27 << 43) | (p512_27 >> 21))) + 0xaaaaaaaaaaaaaaac;
            ulong p512_28 = (p512_01 + p512_03 - p512_06 - p512_09 + p512_10);
            p512_28 = ((p512_28 >> 2) ^ (p512_28 << 1) ^ ((p512_28 << 19) | (p512_28 >> 45)) ^ ((p512_28 << 53) | (p512_28 >> 11))) + 0xaaaaaaaaaaaaaaad;
            ulong p512_29 = (p512_02 + p512_04 + p512_07 + p512_10 + p512_11);
            p512_29 = ((p512_29 >> 2) ^ (p512_29 << 2) ^ ((p512_29 << 28) | (p512_29 >> 36)) ^ ((p512_29 << 59) | (p512_29 >> 5))) + 0xaaaaaaaaaaaaaaae;
            ulong p512_30 = (p512_03 + t512_20 - p512_11 - p512_12);
            p512_14 = ((p512_30 >> 1) ^ p512_30) + 0xaaaaaaaaaaaaaaaf;
            ulong p512_31 = (p512_12 - p512_04 + t512_19 - p512_09);
            p512_15 = ((p512_31 >> 1) ^ (p512_31 << 3) ^ ((p512_31 << 4) | (p512_31 >> 60)) ^ ((p512_31 << 37) | (p512_31 >> 27))) + 0xaaaaaaaaaaaaaaa0;

            p512_00 = p512_16;
            p512_01 = p512_17;
            p512_02 = p512_18;
            p512_03 = p512_19;
            p512_04 = p512_20;
            p512_05 = p512_21;
            p512_06 = p512_22;
            p512_07 = p512_23;
            p512_08 = p512_24;
            p512_09 = p512_25;
            p512_10 = p512_26;
            p512_11 = p512_27;
            p512_12 = p512_28;
            p512_13 = p512_29;

            p512_16 = ((p512_00 >> 1) ^ (p512_00 << 2) ^ ((p512_00 << 13) | (p512_00 >> 51)) ^ ((p512_00 << 43) | (p512_00 >> 21))) +
                      ((p512_01 >> 2) ^ (p512_01 << 1) ^ ((p512_01 << 19) | (p512_01 >> 45)) ^ ((p512_01 << 53) | (p512_01 >> 11))) +
                      ((p512_02 >> 2) ^ (p512_02 << 2) ^ ((p512_02 << 28) | (p512_02 >> 36)) ^ ((p512_02 << 59) | (p512_02 >> 5))) +
                      ((p512_03 >> 1) ^ (p512_03 << 3) ^ ((p512_03 << 4) | (p512_03 >> 60)) ^ ((p512_03 << 37) | (p512_03 >> 27))) +
                      ((p512_04 >> 1) ^ (p512_04 << 2) ^ ((p512_04 << 13) | (p512_04 >> 51)) ^ ((p512_04 << 43) | (p512_04 >> 21))) +
                      ((p512_05 >> 2) ^ (p512_05 << 1) ^ ((p512_05 << 19) | (p512_05 >> 45)) ^ ((p512_05 << 53) | (p512_05 >> 11))) +
                      ((p512_06 >> 2) ^ (p512_06 << 2) ^ ((p512_06 << 28) | (p512_06 >> 36)) ^ ((p512_06 << 59) | (p512_06 >> 5))) +
                      ((p512_07 >> 1) ^ (p512_07 << 3) ^ ((p512_07 << 4) | (p512_07 >> 60)) ^ ((p512_07 << 37) | (p512_07 >> 27))) +
                      ((p512_08 >> 1) ^ (p512_08 << 2) ^ ((p512_08 << 13) | (p512_08 >> 51)) ^ ((p512_08 << 43) | (p512_08 >> 21))) +
                      ((p512_09 >> 2) ^ (p512_09 << 1) ^ ((p512_09 << 19) | (p512_09 >> 45)) ^ ((p512_09 << 53) | (p512_09 >> 11))) +
                      ((p512_10 >> 2) ^ (p512_10 << 2) ^ ((p512_10 << 28) | (p512_10 >> 36)) ^ ((p512_10 << 59) | (p512_10 >> 5))) +
                      ((p512_11 >> 1) ^ (p512_11 << 3) ^ ((p512_11 << 4) | (p512_11 >> 60)) ^ ((p512_11 << 37) | (p512_11 >> 27))) +
                      ((p512_12 >> 1) ^ (p512_12 << 2) ^ ((p512_12 << 13) | (p512_12 >> 51)) ^ ((p512_12 << 43) | (p512_12 >> 21))) +
                      ((p512_13 >> 2) ^ (p512_13 << 1) ^ ((p512_13 << 19) | (p512_13 >> 45)) ^ ((p512_13 << 53) | (p512_13 >> 11))) +
                      ((p512_14 >> 2) ^ (p512_14 << 2) ^ ((p512_14 << 28) | (p512_14 >> 36)) ^ ((p512_14 << 59) | (p512_14 >> 5))) +
                      ((p512_15 >> 1) ^ (p512_15 << 3) ^ ((p512_15 << 4) | (p512_15 >> 60)) ^ ((p512_15 << 37) | (p512_15 >> 27))) +
                      ((td64_00 + td64_03 - td64_10 + 0x5555555555555550) ^ 0xaaaaaaaaaaaaaaa7);

            ulong XL64 = p512_16;

            p512_17 = ((p512_01 >> 1) ^ (p512_01 << 2) ^ ((p512_01 << 13) | (p512_01 >> 51)) ^ ((p512_01 << 43) | (p512_01 >> 21))) +
                      ((p512_02 >> 2) ^ (p512_02 << 1) ^ ((p512_02 << 19) | (p512_02 >> 45)) ^ ((p512_02 << 53) | (p512_02 >> 11))) +
                      ((p512_03 >> 2) ^ (p512_03 << 2) ^ ((p512_03 << 28) | (p512_03 >> 36)) ^ ((p512_03 << 59) | (p512_03 >> 5))) +
                      ((p512_04 >> 1) ^ (p512_04 << 3) ^ ((p512_04 << 4) | (p512_04 >> 60)) ^ ((p512_04 << 37) | (p512_04 >> 27))) +
                      ((p512_05 >> 1) ^ (p512_05 << 2) ^ ((p512_05 << 13) | (p512_05 >> 51)) ^ ((p512_05 << 43) | (p512_05 >> 21))) +
                      ((p512_06 >> 2) ^ (p512_06 << 1) ^ ((p512_06 << 19) | (p512_06 >> 45)) ^ ((p512_06 << 53) | (p512_06 >> 11))) +
                      ((p512_07 >> 2) ^ (p512_07 << 2) ^ ((p512_07 << 28) | (p512_07 >> 36)) ^ ((p512_07 << 59) | (p512_07 >> 5))) +
                      ((p512_08 >> 1) ^ (p512_08 << 3) ^ ((p512_08 << 4) | (p512_08 >> 60)) ^ ((p512_08 << 37) | (p512_08 >> 27))) +
                      ((p512_09 >> 1) ^ (p512_09 << 2) ^ ((p512_09 << 13) | (p512_09 >> 51)) ^ ((p512_09 << 43) | (p512_09 >> 21))) +
                      ((p512_10 >> 2) ^ (p512_10 << 1) ^ ((p512_10 << 19) | (p512_10 >> 45)) ^ ((p512_10 << 53) | (p512_10 >> 11))) +
                      ((p512_11 >> 2) ^ (p512_11 << 2) ^ ((p512_11 << 28) | (p512_11 >> 36)) ^ ((p512_11 << 59) | (p512_11 >> 5))) +
                      ((p512_12 >> 1) ^ (p512_12 << 3) ^ ((p512_12 << 4) | (p512_12 >> 60)) ^ ((p512_12 << 37) | (p512_12 >> 27))) +
                      ((p512_13 >> 1) ^ (p512_13 << 2) ^ ((p512_13 << 13) | (p512_13 >> 51)) ^ ((p512_13 << 43) | (p512_13 >> 21))) +
                      ((p512_14 >> 2) ^ (p512_14 << 1) ^ ((p512_14 << 19) | (p512_14 >> 45)) ^ ((p512_14 << 53) | (p512_14 >> 11))) +
                      ((p512_15 >> 2) ^ (p512_15 << 2) ^ ((p512_15 << 28) | (p512_15 >> 36)) ^ ((p512_15 << 59) | (p512_15 >> 5))) +
                      ((p512_16 >> 1) ^ (p512_16 << 3) ^ ((p512_16 << 4) | (p512_16 >> 60)) ^ ((p512_16 << 37) | (p512_16 >> 27))) +
                      ((td64_01 + td64_04 - td64_11 + 0x5aaaaaaaaaaaaaa5) ^ 0xaaaaaaaaaaaaaaa8);

            XL64 ^= p512_17;
            ulong TempEven64 = p512_14 + p512_12 + p512_10 + p512_08 + p512_06 + p512_04 + p512_02;
            ulong TempOdd64 = p512_15 + p512_13 + p512_11 + p512_09 + p512_07 + p512_05 + p512_03;

            p512_18 = TempEven64 +
                      ((p512_03 << 5) | (p512_03 >> 59)) +
                      ((p512_05 << 11) | (p512_05 >> 53)) +
                      ((p512_07 << 27) | (p512_07 >> 37)) +
                      ((p512_09 << 32) | (p512_09 >> 32)) +
                      ((p512_11 << 37) | (p512_11 >> 27)) +
                      ((p512_13 << 43) | (p512_13 >> 21)) +
                      ((p512_15 << 53) | (p512_15 >> 11)) +
                      ((p512_16 >> 1) ^ p512_16) +
                      ((p512_17 >> 2) ^ p512_17) +
                      ((td64_02 + td64_05 - td64_12 + 0x5ffffffffffffffa) ^ 0xaaaaaaaaaaaaaaa9);

            XL64 ^= p512_18;

            p512_19 = TempOdd64 +
                      ((p512_04 << 5) | (p512_04 >> 59)) +
                      ((p512_06 << 11) | (p512_06 >> 53)) +
                      ((p512_08 << 27) | (p512_08 >> 37)) +
                      ((p512_10 << 32) | (p512_10 >> 32)) +
                      ((p512_12 << 37) | (p512_12 >> 27)) +
                      ((p512_14 << 43) | (p512_14 >> 21)) +
                      ((p512_16 << 53) | (p512_16 >> 11)) +
                      ((p512_17 >> 1) ^ p512_17) +
                      ((p512_18 >> 2) ^ p512_18) +
                      ((td64_03 + td64_06 - td64_13 + 0x655555555555554f) ^ 0xaaaaaaaaaaaaaaaa);

            XL64 ^= p512_19;
            TempEven64 = TempEven64 + p512_16 - p512_02;

            p512_20 = TempEven64 +
                      ((p512_05 << 5) | (p512_05 >> 59)) +
                      ((p512_07 << 11) | (p512_07 >> 53)) +
                      ((p512_09 << 27) | (p512_09 >> 37)) +
                      ((p512_11 << 32) | (p512_11 >> 32)) +
                      ((p512_13 << 37) | (p512_13 >> 27)) +
                      ((p512_15 << 43) | (p512_15 >> 21)) +
                      ((p512_17 << 53) | (p512_17 >> 11)) +
                      ((p512_18 >> 1) ^ p512_18) +
                      ((p512_19 >> 2) ^ p512_19) +
                      ((td64_04 + td64_07 - td64_14 + 0x6aaaaaaaaaaaaaa4) ^ 0xaaaaaaaaaaaaaaab);

            XL64 ^= p512_20;
            TempOdd64 = TempOdd64 + p512_17 - p512_03;

            p512_21 = TempOdd64 +
                      ((p512_06 << 5) | (p512_06 >> 59)) +
                      ((p512_08 << 11) | (p512_08 >> 53)) +
                      ((p512_10 << 27) | (p512_10 >> 37)) +
                      ((p512_12 << 32) | (p512_12 >> 32)) +
                      ((p512_14 << 37) | (p512_14 >> 27)) +
                      ((p512_16 << 43) | (p512_16 >> 21)) +
                      ((p512_18 << 53) | (p512_18 >> 11)) +
                      ((p512_19 >> 1) ^ p512_19) +
                      ((p512_20 >> 2) ^ p512_20) +
                      ((td64_05 + td64_08 - td64_15 + 0x6ffffffffffffff9) ^ 0xaaaaaaaaaaaaaaac);

            XL64 ^= p512_21;
            TempEven64 += p512_18; TempEven64 -= p512_04;

            p512_22 = TempEven64 +
                      ((p512_07 << 5) | (p512_07 >> 59)) +
                      ((p512_09 << 11) | (p512_09 >> 53)) +
                      ((p512_11 << 27) | (p512_11 >> 37)) +
                      ((p512_13 << 32) | (p512_13 >> 32)) +
                      ((p512_15 << 37) | (p512_15 >> 27)) +
                      ((p512_17 << 43) | (p512_17 >> 21)) +
                      ((p512_19 << 53) | (p512_19 >> 11)) +
                      ((p512_20 >> 1) ^ p512_20) +
                      ((p512_21 >> 2) ^ p512_21) +
                      ((td64_06 + td64_09 - td64_00 + 0x755555555555554e) ^ 0xaaaaaaaaaaaaaaad);

            XL64 ^= p512_22;
            TempOdd64 += p512_19; TempOdd64 -= p512_05;

            p512_23 = TempOdd64 +
                      ((p512_08 << 5) | (p512_08 >> 59)) +
                      ((p512_10 << 11) | (p512_10 >> 53)) +
                      ((p512_12 << 27) | (p512_12 >> 37)) +
                      ((p512_14 << 32) | (p512_14 >> 32)) +
                      ((p512_16 << 37) | (p512_16 >> 27)) +
                      ((p512_18 << 43) | (p512_18 >> 21)) +
                      ((p512_20 << 53) | (p512_20 >> 11)) +
                      ((p512_21 >> 1) ^ p512_21) +
                      ((p512_22 >> 2) ^ p512_22) +
                      ((td64_07 + td64_10 - td64_01 + 0x7aaaaaaaaaaaaaa3) ^ 0xaaaaaaaaaaaaaaae);

            XL64 ^= p512_23;
            TempEven64 += p512_20; TempEven64 -= p512_06;

            p512_24 = TempEven64 +
                      ((p512_09 << 5) | (p512_09 >> 59)) +
                      ((p512_11 << 11) | (p512_11 >> 53)) +
                      ((p512_13 << 27) | (p512_13 >> 37)) +
                      ((p512_15 << 32) | (p512_15 >> 32)) +
                      ((p512_17 << 37) | (p512_17 >> 27)) +
                      ((p512_19 << 43) | (p512_19 >> 21)) +
                      ((p512_21 << 53) | (p512_21 >> 11)) +
                      ((p512_22 >> 1) ^ p512_22) +
                      ((p512_23 >> 2) ^ p512_23) +
                      ((td64_08 + td64_11 - td64_02 + 0x7ffffffffffffff8) ^ 0xaaaaaaaaaaaaaaaf);

            ulong XH64 = XL64 ^ p512_24;
            TempOdd64 += p512_21; TempOdd64 -= p512_07;

            p512_25 = TempOdd64 +
                      ((p512_10 << 5) | (p512_10 >> 59)) +
                      ((p512_12 << 11) | (p512_12 >> 53)) +
                      ((p512_14 << 27) | (p512_14 >> 37)) +
                      ((p512_16 << 32) | (p512_16 >> 32)) +
                      ((p512_18 << 37) | (p512_18 >> 27)) +
                      ((p512_20 << 43) | (p512_20 >> 21)) +
                      ((p512_22 << 53) | (p512_22 >> 11)) +
                      ((p512_23 >> 1) ^ p512_23) +
                      ((p512_24 >> 2) ^ p512_24) +
                      ((td64_09 + td64_12 - td64_03 + 0x855555555555554d) ^ 0xaaaaaaaaaaaaaaa0);

            XH64 ^= p512_25;
            TempEven64 += p512_22; TempEven64 -= p512_08;

            p512_26 = TempEven64 +
                      ((p512_11 << 5) | (p512_11 >> 59)) +
                      ((p512_13 << 11) | (p512_13 >> 53)) +
                      ((p512_15 << 27) | (p512_15 >> 37)) +
                      ((p512_17 << 32) | (p512_17 >> 32)) +
                      ((p512_19 << 37) | (p512_19 >> 27)) +
                      ((p512_21 << 43) | (p512_21 >> 21)) +
                      ((p512_23 << 53) | (p512_23 >> 11)) +
                      ((p512_24 >> 1) ^ p512_24) +
                      ((p512_25 >> 2) ^ p512_25) +
                      ((td64_10 + td64_13 - td64_04 + 0x8aaaaaaaaaaaaaa2) ^ 0xaaaaaaaaaaaaaaa1);

            XH64 ^= p512_26;
            TempOdd64 += p512_23; TempOdd64 -= p512_09;

            p512_27 = TempOdd64 +
                      ((p512_12 << 5) | (p512_12 >> 59)) +
                      ((p512_14 << 11) | (p512_14 >> 53)) +
                      ((p512_16 << 27) | (p512_16 >> 37)) +
                      ((p512_18 << 32) | (p512_18 >> 32)) +
                      ((p512_20 << 37) | (p512_20 >> 27)) +
                      ((p512_22 << 43) | (p512_22 >> 21)) +
                      ((p512_24 << 53) | (p512_24 >> 11)) +
                      ((p512_25 >> 1) ^ p512_25) +
                      ((p512_26 >> 2) ^ p512_26) +
                      ((td64_11 + td64_14 - td64_05 + 0x8ffffffffffffff7) ^ 0xaaaaaaaaaaaaaaa2);

            XH64 ^= p512_27;
            TempEven64 += p512_24; TempEven64 -= p512_10;

            p512_28 = TempEven64 +
                      ((p512_13 << 5) | (p512_13 >> 59)) +
                      ((p512_15 << 11) | (p512_15 >> 53)) +
                      ((p512_17 << 27) | (p512_17 >> 37)) +
                      ((p512_19 << 32) | (p512_19 >> 32)) +
                      ((p512_21 << 37) | (p512_21 >> 27)) +
                      ((p512_23 << 43) | (p512_23 >> 21)) +
                      ((p512_25 << 53) | (p512_25 >> 11)) +
                      ((p512_26 >> 1) ^ p512_26) +
                      ((p512_27 >> 2) ^ p512_27) +
                      ((td64_12 + td64_15 - td64_06 + 0x955555555555554c) ^ 0xaaaaaaaaaaaaaaa3);

            XH64 ^= p512_28;
            TempOdd64 += p512_25; TempOdd64 -= p512_11;

            p512_29 = TempOdd64 +
                      ((p512_14 << 5) | (p512_14 >> 59)) +
                      ((p512_16 << 11) | (p512_16 >> 53)) +
                      ((p512_18 << 27) | (p512_18 >> 37)) +
                      ((p512_20 << 32) | (p512_20 >> 32)) +
                      ((p512_22 << 37) | (p512_22 >> 27)) +
                      ((p512_24 << 43) | (p512_24 >> 21)) +
                      ((p512_26 << 53) | (p512_26 >> 11)) +
                      ((p512_27 >> 1) ^ p512_27) +
                      ((p512_28 >> 2) ^ p512_28) +
                      ((td64_13 + td64_00 - td64_07 + 0x9aaaaaaaaaaaaaa1) ^ 0xaaaaaaaaaaaaaaa4);

            XH64 ^= p512_29;
            TempEven64 += p512_26; TempEven64 -= p512_12;

            p512_30 = TempEven64 +
                      ((p512_15 << 5) | (p512_15 >> 59)) +
                      ((p512_17 << 11) | (p512_17 >> 53)) +
                      ((p512_19 << 27) | (p512_19 >> 37)) +
                      ((p512_21 << 32) | (p512_21 >> 32)) +
                      ((p512_23 << 37) | (p512_23 >> 27)) +
                      ((p512_25 << 43) | (p512_25 >> 21)) +
                      ((p512_27 << 53) | (p512_27 >> 11)) +
                      ((p512_28 >> 1) ^ p512_28) +
                      ((p512_29 >> 2) ^ p512_29) +
                      ((td64_14 + td64_01 - td64_08 + 0x9ffffffffffffff6) ^ 0xaaaaaaaaaaaaaaa5);

            XH64 ^= p512_30;
            TempOdd64 += p512_27; TempOdd64 -= p512_13;

            p512_31 = TempOdd64 +
                      ((p512_16 << 5) | (p512_16 >> 59)) +
                      ((p512_18 << 11) | (p512_18 >> 53)) +
                      ((p512_20 << 27) | (p512_20 >> 37)) +
                      ((p512_22 << 32) | (p512_22 >> 32)) +
                      ((p512_24 << 37) | (p512_24 >> 27)) +
                      ((p512_26 << 43) | (p512_26 >> 21)) +
                      ((p512_28 << 53) | (p512_28 >> 11)) +
                      ((p512_29 >> 1) ^ p512_29) +
                      ((p512_30 >> 2) ^ p512_30) +
                      ((td64_15 + td64_02 - td64_09 + 0xa55555555555554b) ^ 0xaaaaaaaaaaaaaaa6);

            XH64 ^= p512_31;

            m_state[0] = ((XH64 << 5) ^ (p512_16 >> 5) ^ m_state[0]) + (XL64 ^ p512_24 ^ p512_00);
            m_state[1] = ((XH64 >> 7) ^ (p512_17 << 8) ^ m_state[1]) + (XL64 ^ p512_25 ^ p512_01);
            m_state[2] = ((XH64 >> 5) ^ (p512_18 << 5) ^ m_state[2]) + (XL64 ^ p512_26 ^ p512_02);
            m_state[3] = ((XH64 >> 1) ^ (p512_19 << 5) ^ m_state[3]) + (XL64 ^ p512_27 ^ p512_03);
            m_state[4] = ((XH64 >> 3) ^ p512_20 ^ m_state[4]) + (XL64 ^ p512_28 ^ p512_04);
            m_state[5] = ((XH64 << 6) ^ (p512_21 >> 6) ^ m_state[5]) + (XL64 ^ p512_29 ^ p512_05);
            m_state[6] = ((XH64 >> 4) ^ (p512_22 << 6) ^ m_state[6]) + (XL64 ^ p512_30 ^ p512_06);
            m_state[7] = ((XH64 >> 11) ^ (p512_23 << 2) ^ m_state[7]) + (XL64 ^ p512_31 ^ p512_07);

            m_state[8] = ((m_state[4] << 9) | (m_state[4] >> 55)) + (XH64 ^ p512_24 ^ m_state[8]) + ((XL64 << 8) ^ p512_23 ^ p512_08);
            m_state[9] = ((m_state[5] << 10) | (m_state[5] >> 54)) + (XH64 ^ p512_25 ^ m_state[9]) + ((XL64 >> 6) ^ p512_16 ^ p512_09);
            m_state[10] = ((m_state[6] << 11) | (m_state[6] >> 53)) + (XH64 ^ p512_26 ^ m_state[10]) + ((XL64 << 6) ^ p512_17 ^ p512_10);
            m_state[11] = ((m_state[7] << 12) | (m_state[7] >> 52)) + (XH64 ^ p512_27 ^ m_state[11]) + ((XL64 << 4) ^ p512_18 ^ p512_11);
            m_state[12] = ((m_state[0] << 13) | (m_state[0] >> 51)) + (XH64 ^ p512_28 ^ m_state[12]) + ((XL64 >> 3) ^ p512_19 ^ p512_12);
            m_state[13] = ((m_state[1] << 14) | (m_state[1] >> 50)) + (XH64 ^ p512_29 ^ m_state[13]) + ((XL64 >> 4) ^ p512_20 ^ p512_13);
            m_state[14] = ((m_state[2] << 15) | (m_state[2] >> 49)) + (XH64 ^ p512_30 ^ m_state[14]) + ((XL64 >> 7) ^ p512_21 ^ p512_14);
            m_state[15] = ((m_state[3] << 16) | (m_state[3] >> 48)) + (XH64 ^ p512_31 ^ m_state[15]) + ((XL64 >> 2) ^ p512_22 ^ p512_15);
        }

        protected override byte[] GetResult()
        {
            byte[] result = new byte[HashSize];

            byte[] state = Converters.ConvertULongsToBytes(m_state);

            if (HashSize == 48)
                Array.Copy(state, 80, result, 0, HashSize);
            else
                Array.Copy(state, 64, result, 0, HashSize);

            return result;
        }

        public override void Initialize()
        {
            m_processed_bytes = 0;

            if (HashSize == 48)
                Array.Copy(s_initial_state_384, m_state, 16);
            else
                Array.Copy(s_initial_state_512, m_state, 16);

            Array.Clear(m_state, 16, 16);

            base.Initialize();
        }
    }
}